167196661SRafal Jaworowski /*- 267196661SRafal Jaworowski * Copyright (C) 2006-2008 Semihalf 367196661SRafal Jaworowski * All rights reserved. 467196661SRafal Jaworowski * 567196661SRafal Jaworowski * Written by: Piotr Kruszynski <ppk@semihalf.com> 667196661SRafal Jaworowski * 767196661SRafal Jaworowski * Redistribution and use in source and binary forms, with or without 867196661SRafal Jaworowski * modification, are permitted provided that the following conditions 967196661SRafal Jaworowski * are met: 1067196661SRafal Jaworowski * 1. Redistributions of source code must retain the above copyright 1167196661SRafal Jaworowski * notice, this list of conditions and the following disclaimer. 1267196661SRafal Jaworowski * 2. Redistributions in binary form must reproduce the above copyright 1367196661SRafal Jaworowski * notice, this list of conditions and the following disclaimer in the 1467196661SRafal Jaworowski * documentation and/or other materials provided with the distribution. 1567196661SRafal Jaworowski * 3. The name of the author may not be used to endorse or promote products 1667196661SRafal Jaworowski * derived from this software without specific prior written permission. 1767196661SRafal Jaworowski * 1867196661SRafal Jaworowski * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1967196661SRafal Jaworowski * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2067196661SRafal Jaworowski * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 2167196661SRafal Jaworowski * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2267196661SRafal Jaworowski * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 2367196661SRafal Jaworowski * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 2467196661SRafal Jaworowski * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 2567196661SRafal Jaworowski * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 2667196661SRafal Jaworowski * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 2767196661SRafal Jaworowski * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2867196661SRafal Jaworowski */ 2967196661SRafal Jaworowski 3067196661SRafal Jaworowski /* 3167196661SRafal Jaworowski * Freescale integrated Three-Speed Ethernet Controller (TSEC) driver. 3267196661SRafal Jaworowski */ 3367196661SRafal Jaworowski #include <sys/cdefs.h> 3467196661SRafal Jaworowski __FBSDID("$FreeBSD$"); 3567196661SRafal Jaworowski 3667196661SRafal Jaworowski #include <sys/param.h> 3767196661SRafal Jaworowski #include <sys/systm.h> 3867196661SRafal Jaworowski #include <sys/endian.h> 3967196661SRafal Jaworowski #include <sys/mbuf.h> 4067196661SRafal Jaworowski #include <sys/kernel.h> 4167196661SRafal Jaworowski #include <sys/module.h> 4267196661SRafal Jaworowski #include <sys/socket.h> 4367196661SRafal Jaworowski #include <sys/sysctl.h> 4467196661SRafal Jaworowski 4567196661SRafal Jaworowski #include <net/if.h> 4667196661SRafal Jaworowski #include <net/if_dl.h> 4767196661SRafal Jaworowski #include <net/if_media.h> 4867196661SRafal Jaworowski 4967196661SRafal Jaworowski #include <net/bpf.h> 5067196661SRafal Jaworowski #include <sys/sockio.h> 5167196661SRafal Jaworowski #include <sys/bus.h> 5267196661SRafal Jaworowski #include <machine/bus.h> 5367196661SRafal Jaworowski #include <sys/rman.h> 5467196661SRafal Jaworowski #include <machine/resource.h> 5567196661SRafal Jaworowski 5667196661SRafal Jaworowski #include <net/ethernet.h> 5767196661SRafal Jaworowski #include <net/if_arp.h> 5867196661SRafal Jaworowski 5967196661SRafal Jaworowski #include <net/if_types.h> 6067196661SRafal Jaworowski #include <net/if_vlan_var.h> 6167196661SRafal Jaworowski 6267196661SRafal Jaworowski #include <dev/mii/mii.h> 6367196661SRafal Jaworowski #include <dev/mii/miivar.h> 6467196661SRafal Jaworowski 6567196661SRafal Jaworowski #include <machine/ocpbus.h> 6667196661SRafal Jaworowski 6767196661SRafal Jaworowski #include <dev/tsec/if_tsec.h> 6867196661SRafal Jaworowski #include <dev/tsec/if_tsecreg.h> 6967196661SRafal Jaworowski 7067196661SRafal Jaworowski #include "miibus_if.h" 7167196661SRafal Jaworowski 7267196661SRafal Jaworowski #define TSEC_DEBUG 7367196661SRafal Jaworowski 7467196661SRafal Jaworowski #ifdef TSEC_DEBUG 7567196661SRafal Jaworowski #define PDEBUG(a) {printf("%s:%d: ", __func__, __LINE__), printf a; printf("\n");} 7667196661SRafal Jaworowski #else 7767196661SRafal Jaworowski #define PDEBUG(a) /* nop */ 7867196661SRafal Jaworowski #endif 7967196661SRafal Jaworowski 8067196661SRafal Jaworowski static int tsec_probe(device_t dev); 8167196661SRafal Jaworowski static int tsec_attach(device_t dev); 8267196661SRafal Jaworowski static int tsec_setup_intr(device_t dev, struct resource **ires, 8367196661SRafal Jaworowski void **ihand, int *irid, driver_intr_t handler, const char *iname); 8467196661SRafal Jaworowski static void tsec_release_intr(device_t dev, struct resource *ires, 8567196661SRafal Jaworowski void *ihand, int irid, const char *iname); 8667196661SRafal Jaworowski static void tsec_free_dma(struct tsec_softc *sc); 8767196661SRafal Jaworowski static int tsec_detach(device_t dev); 8867196661SRafal Jaworowski static void tsec_shutdown(device_t dev); 8967196661SRafal Jaworowski static int tsec_suspend(device_t dev); /* XXX */ 9067196661SRafal Jaworowski static int tsec_resume(device_t dev); /* XXX */ 9167196661SRafal Jaworowski 9267196661SRafal Jaworowski static void tsec_init(void *xsc); 9367196661SRafal Jaworowski static void tsec_init_locked(struct tsec_softc *sc); 9467196661SRafal Jaworowski static void tsec_set_mac_address(struct tsec_softc *sc); 9567196661SRafal Jaworowski static void tsec_dma_ctl(struct tsec_softc *sc, int state); 9667196661SRafal Jaworowski static void tsec_intrs_ctl(struct tsec_softc *sc, int state); 9767196661SRafal Jaworowski static void tsec_reset_mac(struct tsec_softc *sc); 9867196661SRafal Jaworowski 9967196661SRafal Jaworowski static void tsec_watchdog(struct ifnet *ifp); 10067196661SRafal Jaworowski static void tsec_start(struct ifnet *ifp); 10167196661SRafal Jaworowski static void tsec_start_locked(struct ifnet *ifp); 10267196661SRafal Jaworowski static int tsec_encap(struct tsec_softc *sc, 10367196661SRafal Jaworowski struct mbuf *m_head); 10467196661SRafal Jaworowski static void tsec_setfilter(struct tsec_softc *sc); 10567196661SRafal Jaworowski static int tsec_ioctl(struct ifnet *ifp, u_long command, 10667196661SRafal Jaworowski caddr_t data); 10767196661SRafal Jaworowski static int tsec_ifmedia_upd(struct ifnet *ifp); 10867196661SRafal Jaworowski static void tsec_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr); 10967196661SRafal Jaworowski static int tsec_new_rxbuf(bus_dma_tag_t tag, bus_dmamap_t map, 11067196661SRafal Jaworowski struct mbuf **mbufp, uint32_t *paddr); 11167196661SRafal Jaworowski static void tsec_map_dma_addr(void *arg, bus_dma_segment_t *segs, 11267196661SRafal Jaworowski int nseg, int error); 11367196661SRafal Jaworowski static int tsec_alloc_dma_desc(device_t dev, bus_dma_tag_t *dtag, 11467196661SRafal Jaworowski bus_dmamap_t *dmap, bus_size_t dsize, void **vaddr, void *raddr, 11567196661SRafal Jaworowski const char *dname); 11667196661SRafal Jaworowski static void tsec_free_dma_desc(bus_dma_tag_t dtag, bus_dmamap_t dmap, 11767196661SRafal Jaworowski void *vaddr); 11867196661SRafal Jaworowski 11967196661SRafal Jaworowski static void tsec_stop(struct tsec_softc *sc); 12067196661SRafal Jaworowski 12167196661SRafal Jaworowski static void tsec_receive_intr(void *arg); 12267196661SRafal Jaworowski static void tsec_transmit_intr(void *arg); 12367196661SRafal Jaworowski static void tsec_error_intr(void *arg); 12467196661SRafal Jaworowski 12567196661SRafal Jaworowski static void tsec_tick(void *arg); 12667196661SRafal Jaworowski static int tsec_miibus_readreg(device_t dev, int phy, int reg); 12767196661SRafal Jaworowski static void tsec_miibus_writereg(device_t dev, int phy, int reg, int value); 12867196661SRafal Jaworowski static void tsec_miibus_statchg(device_t dev); 12967196661SRafal Jaworowski 13067196661SRafal Jaworowski static struct tsec_softc *tsec0_sc = NULL; /* XXX ugly hack! */ 13167196661SRafal Jaworowski 13267196661SRafal Jaworowski static device_method_t tsec_methods[] = { 13367196661SRafal Jaworowski /* Device interface */ 13467196661SRafal Jaworowski DEVMETHOD(device_probe, tsec_probe), 13567196661SRafal Jaworowski DEVMETHOD(device_attach, tsec_attach), 13667196661SRafal Jaworowski DEVMETHOD(device_detach, tsec_detach), 13767196661SRafal Jaworowski DEVMETHOD(device_shutdown, tsec_shutdown), 13867196661SRafal Jaworowski DEVMETHOD(device_suspend, tsec_suspend), 13967196661SRafal Jaworowski DEVMETHOD(device_resume, tsec_resume), 14067196661SRafal Jaworowski 14167196661SRafal Jaworowski /* bus interface */ 14267196661SRafal Jaworowski DEVMETHOD(bus_print_child, bus_generic_print_child), 14367196661SRafal Jaworowski DEVMETHOD(bus_driver_added, bus_generic_driver_added), 14467196661SRafal Jaworowski 14567196661SRafal Jaworowski /* MII interface */ 14667196661SRafal Jaworowski DEVMETHOD(miibus_readreg, tsec_miibus_readreg), 14767196661SRafal Jaworowski DEVMETHOD(miibus_writereg, tsec_miibus_writereg), 14867196661SRafal Jaworowski DEVMETHOD(miibus_statchg, tsec_miibus_statchg), 14967196661SRafal Jaworowski { 0, 0 } 15067196661SRafal Jaworowski }; 15167196661SRafal Jaworowski 15267196661SRafal Jaworowski static driver_t tsec_driver = { 15367196661SRafal Jaworowski "tsec", 15467196661SRafal Jaworowski tsec_methods, 15567196661SRafal Jaworowski sizeof(struct tsec_softc), 15667196661SRafal Jaworowski }; 15767196661SRafal Jaworowski 15867196661SRafal Jaworowski static devclass_t tsec_devclass; 15967196661SRafal Jaworowski 16067196661SRafal Jaworowski DRIVER_MODULE(tsec, ocpbus, tsec_driver, tsec_devclass, 0, 0); 16167196661SRafal Jaworowski DRIVER_MODULE(miibus, tsec, miibus_driver, miibus_devclass, 0, 0); 16267196661SRafal Jaworowski MODULE_DEPEND(tsec, ether, 1, 1, 1); 16367196661SRafal Jaworowski MODULE_DEPEND(tsec, miibus, 1, 1, 1); 16467196661SRafal Jaworowski 16567196661SRafal Jaworowski static void 16667196661SRafal Jaworowski tsec_get_hwaddr(struct tsec_softc *sc, uint8_t *addr) 16767196661SRafal Jaworowski { 16867196661SRafal Jaworowski union { 16967196661SRafal Jaworowski uint32_t reg[2]; 17067196661SRafal Jaworowski uint8_t addr[6]; 17167196661SRafal Jaworowski } curmac; 17267196661SRafal Jaworowski uint32_t a[6]; 17367196661SRafal Jaworowski int count, i; 17467196661SRafal Jaworowski char *cp; 17567196661SRafal Jaworowski 17667196661SRafal Jaworowski /* Use the currently programmed MAC address by default. */ 17767196661SRafal Jaworowski curmac.reg[0] = TSEC_READ(sc, TSEC_REG_MACSTNADDR1); 17867196661SRafal Jaworowski curmac.reg[1] = TSEC_READ(sc, TSEC_REG_MACSTNADDR2); 17967196661SRafal Jaworowski for (i = 0; i < 6; i++) 18067196661SRafal Jaworowski a[5-i] = curmac.addr[i]; 18167196661SRafal Jaworowski 18267196661SRafal Jaworowski cp = getenv("ethaddr"); 18367196661SRafal Jaworowski if (cp != NULL) { 18467196661SRafal Jaworowski count = sscanf(cp, "%x:%x:%x:%x:%x:%x", &a[0], &a[1], &a[2], 18567196661SRafal Jaworowski &a[3], &a[4], &a[5]); 18667196661SRafal Jaworowski freeenv(cp); 18767196661SRafal Jaworowski } 18867196661SRafal Jaworowski 18967196661SRafal Jaworowski addr[0] = a[0]; 19067196661SRafal Jaworowski addr[1] = a[1]; 19167196661SRafal Jaworowski addr[2] = a[2]; 19267196661SRafal Jaworowski addr[3] = a[3]; 19367196661SRafal Jaworowski addr[4] = a[4]; 19467196661SRafal Jaworowski addr[5] = a[5]; 19567196661SRafal Jaworowski } 19667196661SRafal Jaworowski 19767196661SRafal Jaworowski static void 19867196661SRafal Jaworowski tsec_init(void *xsc) 19967196661SRafal Jaworowski { 20067196661SRafal Jaworowski struct tsec_softc *sc = xsc; 20167196661SRafal Jaworowski 20267196661SRafal Jaworowski TSEC_GLOBAL_LOCK(sc); 20367196661SRafal Jaworowski tsec_init_locked(sc); 20467196661SRafal Jaworowski TSEC_GLOBAL_UNLOCK(sc); 20567196661SRafal Jaworowski } 20667196661SRafal Jaworowski 20767196661SRafal Jaworowski static void 20867196661SRafal Jaworowski tsec_init_locked(struct tsec_softc *sc) 20967196661SRafal Jaworowski { 21067196661SRafal Jaworowski struct tsec_desc *tx_desc = sc->tsec_tx_vaddr; 21167196661SRafal Jaworowski struct tsec_desc *rx_desc = sc->tsec_rx_vaddr; 21267196661SRafal Jaworowski struct ifnet *ifp = sc->tsec_ifp; 21367196661SRafal Jaworowski uint32_t timeout; 21467196661SRafal Jaworowski uint32_t val; 21567196661SRafal Jaworowski uint32_t i; 21667196661SRafal Jaworowski 21767196661SRafal Jaworowski TSEC_GLOBAL_LOCK_ASSERT(sc); 21867196661SRafal Jaworowski tsec_stop(sc); 21967196661SRafal Jaworowski 22067196661SRafal Jaworowski /* 22167196661SRafal Jaworowski * These steps are according to the MPC8555E PowerQUICCIII RM: 22267196661SRafal Jaworowski * 14.7 Initialization/Application Information 22367196661SRafal Jaworowski */ 22467196661SRafal Jaworowski 22567196661SRafal Jaworowski /* Step 1: soft reset MAC */ 22667196661SRafal Jaworowski tsec_reset_mac(sc); 22767196661SRafal Jaworowski 22867196661SRafal Jaworowski /* Step 2: Initialize MACCFG2 */ 22967196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_MACCFG2, 23067196661SRafal Jaworowski TSEC_MACCFG2_FULLDUPLEX | /* Full Duplex = 1 */ 23167196661SRafal Jaworowski TSEC_MACCFG2_PADCRC | /* PAD/CRC append */ 23267196661SRafal Jaworowski TSEC_MACCFG2_GMII | /* I/F Mode bit */ 23367196661SRafal Jaworowski TSEC_MACCFG2_PRECNT /* Preamble count = 7 */ 23467196661SRafal Jaworowski ); 23567196661SRafal Jaworowski 23667196661SRafal Jaworowski /* Step 3: Initialize ECNTRL 23767196661SRafal Jaworowski * While the documentation states that R100M is ignored if RPM is 23867196661SRafal Jaworowski * not set, it does seem to be needed to get the orange boxes to 23967196661SRafal Jaworowski * work (which have a Marvell 88E1111 PHY). Go figure. 24067196661SRafal Jaworowski */ 24167196661SRafal Jaworowski 24267196661SRafal Jaworowski /* 24367196661SRafal Jaworowski * XXX kludge - use circumstancial evidence to program ECNTRL 24467196661SRafal Jaworowski * correctly. Ideally we need some board information to guide 24567196661SRafal Jaworowski * us here. 24667196661SRafal Jaworowski */ 24767196661SRafal Jaworowski i = TSEC_READ(sc, TSEC_REG_ID2); 24867196661SRafal Jaworowski val = (i & 0xffff) 24967196661SRafal Jaworowski ? (TSEC_ECNTRL_TBIM | TSEC_ECNTRL_SGMIIM) /* Sumatra */ 25067196661SRafal Jaworowski : TSEC_ECNTRL_R100M; /* Orange + CDS */ 25167196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_ECNTRL, TSEC_ECNTRL_STEN | val); 25267196661SRafal Jaworowski 25367196661SRafal Jaworowski /* Step 4: Initialize MAC station address */ 25467196661SRafal Jaworowski tsec_set_mac_address(sc); 25567196661SRafal Jaworowski 25667196661SRafal Jaworowski /* 25767196661SRafal Jaworowski * Step 5: Assign a Physical address to the TBI so as to not conflict 25867196661SRafal Jaworowski * with the external PHY physical address 25967196661SRafal Jaworowski */ 26067196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_TBIPA, 5); 26167196661SRafal Jaworowski 26267196661SRafal Jaworowski /* Step 6: Reset the management interface */ 26367196661SRafal Jaworowski TSEC_WRITE(tsec0_sc, TSEC_REG_MIIMCFG, TSEC_MIIMCFG_RESETMGMT); 26467196661SRafal Jaworowski 26567196661SRafal Jaworowski /* Step 7: Setup the MII Mgmt clock speed */ 26667196661SRafal Jaworowski TSEC_WRITE(tsec0_sc, TSEC_REG_MIIMCFG, TSEC_MIIMCFG_CLKDIV28); 26767196661SRafal Jaworowski 26867196661SRafal Jaworowski /* Step 8: Read MII Mgmt indicator register and check for Busy = 0 */ 26967196661SRafal Jaworowski timeout = TSEC_READ_RETRY; 27067196661SRafal Jaworowski while (--timeout && (TSEC_READ(tsec0_sc, TSEC_REG_MIIMIND) & 27167196661SRafal Jaworowski TSEC_MIIMIND_BUSY)) 27267196661SRafal Jaworowski DELAY(TSEC_READ_DELAY); 27367196661SRafal Jaworowski if (timeout == 0) { 27467196661SRafal Jaworowski if_printf(ifp, "tsec_init_locked(): Mgmt busy timeout\n"); 27567196661SRafal Jaworowski return; 27667196661SRafal Jaworowski } 27767196661SRafal Jaworowski 27867196661SRafal Jaworowski /* Step 9: Setup the MII Mgmt */ 27967196661SRafal Jaworowski mii_mediachg(sc->tsec_mii); 28067196661SRafal Jaworowski 28167196661SRafal Jaworowski /* Step 10: Clear IEVENT register */ 28267196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_IEVENT, 0xffffffff); 28367196661SRafal Jaworowski 28467196661SRafal Jaworowski /* Step 11: Initialize IMASK */ 28567196661SRafal Jaworowski tsec_intrs_ctl(sc, 1); 28667196661SRafal Jaworowski 28767196661SRafal Jaworowski /* Step 12: Initialize IADDRn */ 28867196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_IADDR0, 0); 28967196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_IADDR1, 0); 29067196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_IADDR2, 0); 29167196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_IADDR3, 0); 29267196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_IADDR4, 0); 29367196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_IADDR5, 0); 29467196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_IADDR6, 0); 29567196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_IADDR7, 0); 29667196661SRafal Jaworowski 29767196661SRafal Jaworowski /* Step 13: Initialize GADDRn */ 29867196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_GADDR0, 0); 29967196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_GADDR1, 0); 30067196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_GADDR2, 0); 30167196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_GADDR3, 0); 30267196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_GADDR4, 0); 30367196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_GADDR5, 0); 30467196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_GADDR6, 0); 30567196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_GADDR7, 0); 30667196661SRafal Jaworowski 30767196661SRafal Jaworowski /* Step 14: Initialize RCTRL */ 30867196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_RCTRL, 0); 30967196661SRafal Jaworowski 31067196661SRafal Jaworowski /* Step 15: Initialize DMACTRL */ 31167196661SRafal Jaworowski tsec_dma_ctl(sc, 1); 31267196661SRafal Jaworowski 31367196661SRafal Jaworowski /* Step 16: Initialize FIFO_PAUSE_CTRL */ 31467196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_FIFO_PAUSE_CTRL, TSEC_FIFO_PAUSE_CTRL_EN); 31567196661SRafal Jaworowski 31667196661SRafal Jaworowski /* 31767196661SRafal Jaworowski * Step 17: Initialize transmit/receive descriptor rings. 31867196661SRafal Jaworowski * Initialize TBASE and RBASE. 31967196661SRafal Jaworowski */ 32067196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_TBASE, sc->tsec_tx_raddr); 32167196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_RBASE, sc->tsec_rx_raddr); 32267196661SRafal Jaworowski 32367196661SRafal Jaworowski for (i = 0; i < TSEC_TX_NUM_DESC; i++) { 32467196661SRafal Jaworowski tx_desc[i].bufptr = 0; 32567196661SRafal Jaworowski tx_desc[i].length = 0; 32667196661SRafal Jaworowski tx_desc[i].flags = ((i == TSEC_TX_NUM_DESC-1) ? TSEC_TXBD_W : 0); 32767196661SRafal Jaworowski } 32867196661SRafal Jaworowski bus_dmamap_sync(sc->tsec_tx_dtag, sc->tsec_tx_dmap, BUS_DMASYNC_PREREAD | 32967196661SRafal Jaworowski BUS_DMASYNC_PREWRITE); 33067196661SRafal Jaworowski 33167196661SRafal Jaworowski for (i = 0; i < TSEC_RX_NUM_DESC; i++) { 33267196661SRafal Jaworowski rx_desc[i].bufptr = sc->rx_data[i].paddr; 33367196661SRafal Jaworowski rx_desc[i].length = 0; 33467196661SRafal Jaworowski rx_desc[i].flags = TSEC_RXBD_E | TSEC_RXBD_I | 33567196661SRafal Jaworowski ((i == TSEC_RX_NUM_DESC-1) ? TSEC_RXBD_W : 0); 33667196661SRafal Jaworowski } 33767196661SRafal Jaworowski bus_dmamap_sync(sc->tsec_rx_dtag, sc->tsec_rx_dmap, BUS_DMASYNC_PREREAD | 33867196661SRafal Jaworowski BUS_DMASYNC_PREWRITE); 33967196661SRafal Jaworowski 34067196661SRafal Jaworowski /* Step 18: Initialize the maximum and minimum receive buffer length */ 34167196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_MRBLR, TSEC_DEFAULT_MAX_RX_BUFFER_SIZE); 34267196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_MINFLR, TSEC_DEFAULT_MIN_RX_BUFFER_SIZE); 34367196661SRafal Jaworowski 34467196661SRafal Jaworowski /* Step 19: Enable Rx and RxBD sdata snooping */ 34567196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_ATTR, TSEC_ATTR_RDSEN | TSEC_ATTR_RBDSEN); 34667196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_ATTRELI, 0); 34767196661SRafal Jaworowski 34867196661SRafal Jaworowski /* Step 20: Reset collision counters in hardware */ 34967196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_MON_TSCL, 0); 35067196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_MON_TMCL, 0); 35167196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_MON_TLCL, 0); 35267196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_MON_TXCL, 0); 35367196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_MON_TNCL, 0); 35467196661SRafal Jaworowski 35567196661SRafal Jaworowski /* Step 21: Mask all CAM interrupts */ 35667196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_MON_CAM1, 0xffffffff); 35767196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_MON_CAM2, 0xffffffff); 35867196661SRafal Jaworowski 35967196661SRafal Jaworowski /* Step 22: Enable Rx and Tx */ 36067196661SRafal Jaworowski val = TSEC_READ(sc, TSEC_REG_MACCFG1); 36167196661SRafal Jaworowski val |= (TSEC_MACCFG1_RX_EN | TSEC_MACCFG1_TX_EN); 36267196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_MACCFG1, val); 36367196661SRafal Jaworowski 36467196661SRafal Jaworowski /* Step 23: Reset TSEC counters for Tx and Rx rings */ 36567196661SRafal Jaworowski TSEC_TX_RX_COUNTERS_INIT(sc); 36667196661SRafal Jaworowski 36767196661SRafal Jaworowski /* Step 24: Activate timer for PHY */ 36867196661SRafal Jaworowski callout_reset(&sc->tsec_tick_ch, hz, tsec_tick, sc); 36967196661SRafal Jaworowski 37067196661SRafal Jaworowski /* Step 25: Activate network interface */ 37167196661SRafal Jaworowski ifp->if_drv_flags |= IFF_DRV_RUNNING; 37267196661SRafal Jaworowski ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 37367196661SRafal Jaworowski ifp->if_timer = 0; 37467196661SRafal Jaworowski sc->tsec_if_flags = ifp->if_flags; 37567196661SRafal Jaworowski } 37667196661SRafal Jaworowski 37767196661SRafal Jaworowski static void 37867196661SRafal Jaworowski tsec_set_mac_address(struct tsec_softc *sc) 37967196661SRafal Jaworowski { 38067196661SRafal Jaworowski uint32_t macbuf[2] = { 0, 0 }; 38167196661SRafal Jaworowski int i; 38267196661SRafal Jaworowski char *macbufp; 38367196661SRafal Jaworowski char *curmac; 38467196661SRafal Jaworowski 38567196661SRafal Jaworowski TSEC_GLOBAL_LOCK_ASSERT(sc); 38667196661SRafal Jaworowski 38767196661SRafal Jaworowski KASSERT((ETHER_ADDR_LEN <= sizeof(macbuf)), 38867196661SRafal Jaworowski ("tsec_set_mac_address: (%d <= %d", 38967196661SRafal Jaworowski ETHER_ADDR_LEN, sizeof(macbuf))); 39067196661SRafal Jaworowski 39167196661SRafal Jaworowski macbufp = (char *)macbuf; 39267196661SRafal Jaworowski curmac = (char *)IF_LLADDR(sc->tsec_ifp); 39367196661SRafal Jaworowski 39467196661SRafal Jaworowski /* Correct order of MAC address bytes */ 39567196661SRafal Jaworowski for (i = 1; i <= ETHER_ADDR_LEN; i++) 39667196661SRafal Jaworowski macbufp[ETHER_ADDR_LEN-i] = curmac[i-1]; 39767196661SRafal Jaworowski 39867196661SRafal Jaworowski /* Initialize MAC station address MACSTNADDR2 and MACSTNADDR1 */ 39967196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_MACSTNADDR2, macbuf[1]); 40067196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_MACSTNADDR1, macbuf[0]); 40167196661SRafal Jaworowski } 40267196661SRafal Jaworowski 40367196661SRafal Jaworowski /* 40467196661SRafal Jaworowski * DMA control function, if argument state is: 40567196661SRafal Jaworowski * 0 - DMA engine will be disabled 40667196661SRafal Jaworowski * 1 - DMA engine will be enabled 40767196661SRafal Jaworowski */ 40867196661SRafal Jaworowski static void 40967196661SRafal Jaworowski tsec_dma_ctl(struct tsec_softc *sc, int state) 41067196661SRafal Jaworowski { 41167196661SRafal Jaworowski device_t dev; 41267196661SRafal Jaworowski uint32_t dma_flags; 41367196661SRafal Jaworowski uint32_t timeout; 41467196661SRafal Jaworowski 41567196661SRafal Jaworowski dev = sc->dev; 41667196661SRafal Jaworowski 41767196661SRafal Jaworowski dma_flags = TSEC_READ(sc, TSEC_REG_DMACTRL); 41867196661SRafal Jaworowski 41967196661SRafal Jaworowski switch (state) { 42067196661SRafal Jaworowski case 0: 42167196661SRafal Jaworowski /* Temporarily clear stop graceful stop bits. */ 42267196661SRafal Jaworowski tsec_dma_ctl(sc, 1000); 42367196661SRafal Jaworowski 42467196661SRafal Jaworowski /* Set it again */ 42567196661SRafal Jaworowski dma_flags |= (TSEC_DMACTRL_GRS | TSEC_DMACTRL_GTS); 42667196661SRafal Jaworowski break; 42767196661SRafal Jaworowski case 1000: 42867196661SRafal Jaworowski case 1: 42967196661SRafal Jaworowski /* Set write with response (WWR), wait (WOP) and snoop bits */ 43067196661SRafal Jaworowski dma_flags |= (TSEC_DMACTRL_TDSEN | TSEC_DMACTRL_TBDSEN | 43167196661SRafal Jaworowski DMACTRL_WWR | DMACTRL_WOP); 43267196661SRafal Jaworowski 43367196661SRafal Jaworowski /* Clear graceful stop bits */ 43467196661SRafal Jaworowski dma_flags &= ~(TSEC_DMACTRL_GRS | TSEC_DMACTRL_GTS); 43567196661SRafal Jaworowski break; 43667196661SRafal Jaworowski default: 43767196661SRafal Jaworowski device_printf(dev, "tsec_dma_ctl(): unknown state value: %d\n", 43867196661SRafal Jaworowski state); 43967196661SRafal Jaworowski } 44067196661SRafal Jaworowski 44167196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_DMACTRL, dma_flags); 44267196661SRafal Jaworowski 44367196661SRafal Jaworowski switch (state) { 44467196661SRafal Jaworowski case 0: 44567196661SRafal Jaworowski /* Wait for DMA stop */ 44667196661SRafal Jaworowski timeout = TSEC_READ_RETRY; 44767196661SRafal Jaworowski while (--timeout && (!(TSEC_READ(sc, TSEC_REG_IEVENT) & 44867196661SRafal Jaworowski (TSEC_IEVENT_GRSC | TSEC_IEVENT_GTSC)))) 44967196661SRafal Jaworowski DELAY(TSEC_READ_DELAY); 45067196661SRafal Jaworowski 45167196661SRafal Jaworowski if (timeout == 0) 45267196661SRafal Jaworowski device_printf(dev, "tsec_dma_ctl(): timeout!\n"); 45367196661SRafal Jaworowski break; 45467196661SRafal Jaworowski case 1: 45567196661SRafal Jaworowski /* Restart transmission function */ 45667196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_TSTAT, TSEC_TSTAT_THLT); 45767196661SRafal Jaworowski } 45867196661SRafal Jaworowski } 45967196661SRafal Jaworowski 46067196661SRafal Jaworowski /* 46167196661SRafal Jaworowski * Interrupts control function, if argument state is: 46267196661SRafal Jaworowski * 0 - all TSEC interrupts will be masked 46367196661SRafal Jaworowski * 1 - all TSEC interrupts will be unmasked 46467196661SRafal Jaworowski */ 46567196661SRafal Jaworowski static void 46667196661SRafal Jaworowski tsec_intrs_ctl(struct tsec_softc *sc, int state) 46767196661SRafal Jaworowski { 46867196661SRafal Jaworowski device_t dev; 46967196661SRafal Jaworowski 47067196661SRafal Jaworowski dev = sc->dev; 47167196661SRafal Jaworowski 47267196661SRafal Jaworowski switch (state) { 47367196661SRafal Jaworowski case 0: 47467196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_IMASK, 0); 47567196661SRafal Jaworowski break; 47667196661SRafal Jaworowski case 1: 47767196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_IMASK, TSEC_IMASK_BREN | 47867196661SRafal Jaworowski TSEC_IMASK_RXCEN | TSEC_IMASK_BSYEN | 47967196661SRafal Jaworowski TSEC_IMASK_EBERREN | TSEC_IMASK_BTEN | 48067196661SRafal Jaworowski TSEC_IMASK_TXEEN | TSEC_IMASK_TXBEN | 48167196661SRafal Jaworowski TSEC_IMASK_TXFEN | TSEC_IMASK_XFUNEN | 48267196661SRafal Jaworowski TSEC_IMASK_RXFEN 48367196661SRafal Jaworowski ); 48467196661SRafal Jaworowski break; 48567196661SRafal Jaworowski default: 48667196661SRafal Jaworowski device_printf(dev, "tsec_intrs_ctl(): unknown state value: %d\n", 48767196661SRafal Jaworowski state); 48867196661SRafal Jaworowski } 48967196661SRafal Jaworowski } 49067196661SRafal Jaworowski 49167196661SRafal Jaworowski static void 49267196661SRafal Jaworowski tsec_reset_mac(struct tsec_softc *sc) 49367196661SRafal Jaworowski { 49467196661SRafal Jaworowski uint32_t maccfg1_flags; 49567196661SRafal Jaworowski 49667196661SRafal Jaworowski /* Set soft reset bit */ 49767196661SRafal Jaworowski maccfg1_flags = TSEC_READ(sc, TSEC_REG_MACCFG1); 49867196661SRafal Jaworowski maccfg1_flags |= TSEC_MACCFG1_SOFT_RESET; 49967196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_MACCFG1, maccfg1_flags); 50067196661SRafal Jaworowski 50167196661SRafal Jaworowski /* Clear soft reset bit */ 50267196661SRafal Jaworowski maccfg1_flags = TSEC_READ(sc, TSEC_REG_MACCFG1); 50367196661SRafal Jaworowski maccfg1_flags &= ~TSEC_MACCFG1_SOFT_RESET; 50467196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_MACCFG1, maccfg1_flags); 50567196661SRafal Jaworowski } 50667196661SRafal Jaworowski 50767196661SRafal Jaworowski static void 50867196661SRafal Jaworowski tsec_watchdog(struct ifnet *ifp) 50967196661SRafal Jaworowski { 51067196661SRafal Jaworowski struct tsec_softc *sc = ifp->if_softc; 51167196661SRafal Jaworowski 51267196661SRafal Jaworowski TSEC_GLOBAL_LOCK(sc); 51367196661SRafal Jaworowski 51467196661SRafal Jaworowski ifp->if_oerrors++; 51567196661SRafal Jaworowski if_printf(ifp, "watchdog timeout\n"); 51667196661SRafal Jaworowski 51767196661SRafal Jaworowski tsec_stop(sc); 51867196661SRafal Jaworowski tsec_init_locked(sc); 51967196661SRafal Jaworowski 52067196661SRafal Jaworowski TSEC_GLOBAL_UNLOCK(sc); 52167196661SRafal Jaworowski } 52267196661SRafal Jaworowski 52367196661SRafal Jaworowski static void 52467196661SRafal Jaworowski tsec_start(struct ifnet *ifp) 52567196661SRafal Jaworowski { 52667196661SRafal Jaworowski struct tsec_softc *sc = ifp->if_softc; 52767196661SRafal Jaworowski 52867196661SRafal Jaworowski TSEC_TRANSMIT_LOCK(sc); 52967196661SRafal Jaworowski tsec_start_locked(ifp); 53067196661SRafal Jaworowski TSEC_TRANSMIT_UNLOCK(sc); 53167196661SRafal Jaworowski } 53267196661SRafal Jaworowski 53367196661SRafal Jaworowski 53467196661SRafal Jaworowski static void 53567196661SRafal Jaworowski tsec_start_locked(struct ifnet *ifp) 53667196661SRafal Jaworowski { 53767196661SRafal Jaworowski struct tsec_softc *sc; 53867196661SRafal Jaworowski struct mbuf *m0; 53967196661SRafal Jaworowski struct mbuf *mtmp; 54067196661SRafal Jaworowski unsigned int queued = 0; 54167196661SRafal Jaworowski 54267196661SRafal Jaworowski sc = ifp->if_softc; 54367196661SRafal Jaworowski 54467196661SRafal Jaworowski TSEC_TRANSMIT_LOCK_ASSERT(sc); 54567196661SRafal Jaworowski 54667196661SRafal Jaworowski if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != 54767196661SRafal Jaworowski IFF_DRV_RUNNING) 54867196661SRafal Jaworowski return; 54967196661SRafal Jaworowski 55067196661SRafal Jaworowski if (sc->tsec_link == 0) 55167196661SRafal Jaworowski return; 55267196661SRafal Jaworowski 55367196661SRafal Jaworowski bus_dmamap_sync(sc->tsec_tx_dtag, sc->tsec_tx_dmap, 55467196661SRafal Jaworowski BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 55567196661SRafal Jaworowski 55667196661SRafal Jaworowski for (;;) { 55767196661SRafal Jaworowski /* Get packet from the queue */ 55867196661SRafal Jaworowski IF_DEQUEUE(&ifp->if_snd, m0); 55967196661SRafal Jaworowski if (m0 == NULL) 56067196661SRafal Jaworowski break; 56167196661SRafal Jaworowski 56267196661SRafal Jaworowski mtmp = m_defrag(m0, M_DONTWAIT); 56367196661SRafal Jaworowski if (mtmp) 56467196661SRafal Jaworowski m0 = mtmp; 56567196661SRafal Jaworowski 56667196661SRafal Jaworowski if (tsec_encap(sc, m0)) { 56767196661SRafal Jaworowski IF_PREPEND(&ifp->if_snd, m0); 56867196661SRafal Jaworowski ifp->if_drv_flags |= IFF_DRV_OACTIVE; 56967196661SRafal Jaworowski break; 57067196661SRafal Jaworowski } 57167196661SRafal Jaworowski queued++; 57267196661SRafal Jaworowski BPF_MTAP(ifp, m0); 57367196661SRafal Jaworowski } 57467196661SRafal Jaworowski bus_dmamap_sync(sc->tsec_tx_dtag, sc->tsec_tx_dmap, 57567196661SRafal Jaworowski BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 57667196661SRafal Jaworowski 57767196661SRafal Jaworowski if (queued) { 57867196661SRafal Jaworowski /* Enable transmitter and watchdog timer */ 57967196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_TSTAT, TSEC_TSTAT_THLT); 58067196661SRafal Jaworowski ifp->if_timer = 5; 58167196661SRafal Jaworowski } 58267196661SRafal Jaworowski } 58367196661SRafal Jaworowski 58467196661SRafal Jaworowski static int 58567196661SRafal Jaworowski tsec_encap(struct tsec_softc *sc, struct mbuf *m0) 58667196661SRafal Jaworowski { 58767196661SRafal Jaworowski struct tsec_desc *tx_desc = NULL; 58867196661SRafal Jaworowski struct ifnet *ifp; 58967196661SRafal Jaworowski bus_dma_segment_t segs[TSEC_TX_NUM_DESC]; 59067196661SRafal Jaworowski bus_dmamap_t *mapp; 59167196661SRafal Jaworowski int error; 59267196661SRafal Jaworowski int seg, nsegs; 59367196661SRafal Jaworowski 59467196661SRafal Jaworowski TSEC_TRANSMIT_LOCK_ASSERT(sc); 59567196661SRafal Jaworowski 59667196661SRafal Jaworowski ifp = sc->tsec_ifp; 59767196661SRafal Jaworowski 59867196661SRafal Jaworowski if (TSEC_FREE_TX_DESC(sc) == 0) { 59967196661SRafal Jaworowski /* No free descriptors */ 60067196661SRafal Jaworowski return (-1); 60167196661SRafal Jaworowski } 60267196661SRafal Jaworowski 60367196661SRafal Jaworowski /* Fetch unused map */ 60467196661SRafal Jaworowski mapp = TSEC_ALLOC_TX_MAP(sc); 60567196661SRafal Jaworowski 60667196661SRafal Jaworowski /* Create mapping in DMA memory */ 60767196661SRafal Jaworowski error = bus_dmamap_load_mbuf_sg(sc->tsec_tx_mtag, 60867196661SRafal Jaworowski *mapp, m0, segs, &nsegs, BUS_DMA_NOWAIT); 60967196661SRafal Jaworowski if (error != 0 || nsegs > TSEC_FREE_TX_DESC(sc) || nsegs <= 0) { 61067196661SRafal Jaworowski bus_dmamap_unload(sc->tsec_tx_mtag, *mapp); 61167196661SRafal Jaworowski TSEC_FREE_TX_MAP(sc, mapp); 61267196661SRafal Jaworowski return ((error != 0) ? error : -1); 61367196661SRafal Jaworowski } 61467196661SRafal Jaworowski bus_dmamap_sync(sc->tsec_tx_mtag, *mapp, BUS_DMASYNC_PREWRITE); 61567196661SRafal Jaworowski 61667196661SRafal Jaworowski if ((ifp->if_flags & IFF_DEBUG) && (nsegs > 1)) 61767196661SRafal Jaworowski if_printf(ifp, "TX buffer has %d segments\n", nsegs); 61867196661SRafal Jaworowski 61967196661SRafal Jaworowski /* Everything is ok, now we can send buffers */ 62067196661SRafal Jaworowski for (seg = 0; seg < nsegs; seg++) { 62167196661SRafal Jaworowski tx_desc = TSEC_GET_CUR_TX_DESC(sc); 62267196661SRafal Jaworowski 62367196661SRafal Jaworowski tx_desc->length = segs[seg].ds_len; 62467196661SRafal Jaworowski tx_desc->bufptr = segs[seg].ds_addr; 62567196661SRafal Jaworowski 62667196661SRafal Jaworowski tx_desc->flags = 62767196661SRafal Jaworowski (tx_desc->flags & TSEC_TXBD_W) | /* wrap */ 62867196661SRafal Jaworowski TSEC_TXBD_I | /* interrupt */ 62967196661SRafal Jaworowski TSEC_TXBD_R | /* ready to send */ 63067196661SRafal Jaworowski TSEC_TXBD_TC | /* transmit the CRC sequence 63167196661SRafal Jaworowski * after the last data byte */ 63267196661SRafal Jaworowski ((seg == nsegs-1) ? TSEC_TXBD_L : 0);/* last in frame */ 63367196661SRafal Jaworowski } 63467196661SRafal Jaworowski 63567196661SRafal Jaworowski /* Save mbuf and DMA mapping for release at later stage */ 63667196661SRafal Jaworowski TSEC_PUT_TX_MBUF(sc, m0); 63767196661SRafal Jaworowski TSEC_PUT_TX_MAP(sc, mapp); 63867196661SRafal Jaworowski 63967196661SRafal Jaworowski return (0); 64067196661SRafal Jaworowski } 64167196661SRafal Jaworowski 64267196661SRafal Jaworowski static void 64367196661SRafal Jaworowski tsec_setfilter(struct tsec_softc *sc) 64467196661SRafal Jaworowski { 64567196661SRafal Jaworowski struct ifnet *ifp; 64667196661SRafal Jaworowski uint32_t flags; 64767196661SRafal Jaworowski 64867196661SRafal Jaworowski ifp = sc->tsec_ifp; 64967196661SRafal Jaworowski flags = TSEC_READ(sc, TSEC_REG_RCTRL); 65067196661SRafal Jaworowski 65167196661SRafal Jaworowski /* Promiscuous mode */ 65267196661SRafal Jaworowski if (ifp->if_flags & IFF_PROMISC) 65367196661SRafal Jaworowski flags |= TSEC_RCTRL_PROM; 65467196661SRafal Jaworowski else 65567196661SRafal Jaworowski flags &= ~TSEC_RCTRL_PROM; 65667196661SRafal Jaworowski 65767196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_RCTRL, flags); 65867196661SRafal Jaworowski } 65967196661SRafal Jaworowski 66067196661SRafal Jaworowski static int 66167196661SRafal Jaworowski tsec_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 66267196661SRafal Jaworowski { 66367196661SRafal Jaworowski struct tsec_softc *sc = ifp->if_softc; 66467196661SRafal Jaworowski struct ifreq *ifr = (struct ifreq *)data; 66567196661SRafal Jaworowski device_t dev; 66667196661SRafal Jaworowski int error = 0; 66767196661SRafal Jaworowski 66867196661SRafal Jaworowski dev = sc->dev; 66967196661SRafal Jaworowski 67067196661SRafal Jaworowski switch (command) { 67167196661SRafal Jaworowski case SIOCSIFFLAGS: 67267196661SRafal Jaworowski TSEC_GLOBAL_LOCK(sc); 67367196661SRafal Jaworowski if (ifp->if_flags & IFF_UP) { 67467196661SRafal Jaworowski if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 67567196661SRafal Jaworowski if ((sc->tsec_if_flags ^ ifp->if_flags) & 67667196661SRafal Jaworowski IFF_PROMISC) 67767196661SRafal Jaworowski tsec_setfilter(sc); 67867196661SRafal Jaworowski } else 67967196661SRafal Jaworowski tsec_init_locked(sc); 68067196661SRafal Jaworowski } else { 68167196661SRafal Jaworowski if (ifp->if_drv_flags & IFF_DRV_RUNNING) 68267196661SRafal Jaworowski tsec_stop(sc); 68367196661SRafal Jaworowski } 68467196661SRafal Jaworowski sc->tsec_if_flags = ifp->if_flags; 68567196661SRafal Jaworowski TSEC_GLOBAL_UNLOCK(sc); 68667196661SRafal Jaworowski break; 68767196661SRafal Jaworowski case SIOCGIFMEDIA: 68867196661SRafal Jaworowski case SIOCSIFMEDIA: 68967196661SRafal Jaworowski error = ifmedia_ioctl(ifp, ifr, &sc->tsec_mii->mii_media, 69067196661SRafal Jaworowski command); 69167196661SRafal Jaworowski break; 69267196661SRafal Jaworowski default: 69367196661SRafal Jaworowski error = ether_ioctl(ifp, command, data); 69467196661SRafal Jaworowski } 69567196661SRafal Jaworowski 69667196661SRafal Jaworowski /* Flush buffers if not empty */ 69767196661SRafal Jaworowski if (ifp->if_flags & IFF_UP) 69867196661SRafal Jaworowski tsec_start(ifp); 69967196661SRafal Jaworowski return (error); 70067196661SRafal Jaworowski } 70167196661SRafal Jaworowski 70267196661SRafal Jaworowski static int 70367196661SRafal Jaworowski tsec_ifmedia_upd(struct ifnet *ifp) 70467196661SRafal Jaworowski { 70567196661SRafal Jaworowski struct tsec_softc *sc = ifp->if_softc; 70667196661SRafal Jaworowski struct mii_data *mii; 70767196661SRafal Jaworowski 70867196661SRafal Jaworowski TSEC_TRANSMIT_LOCK(sc); 70967196661SRafal Jaworowski 71067196661SRafal Jaworowski mii = sc->tsec_mii; 71167196661SRafal Jaworowski mii_mediachg(mii); 71267196661SRafal Jaworowski 71367196661SRafal Jaworowski TSEC_TRANSMIT_UNLOCK(sc); 71467196661SRafal Jaworowski return (0); 71567196661SRafal Jaworowski } 71667196661SRafal Jaworowski 71767196661SRafal Jaworowski static void 71867196661SRafal Jaworowski tsec_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 71967196661SRafal Jaworowski { 72067196661SRafal Jaworowski struct tsec_softc *sc = ifp->if_softc; 72167196661SRafal Jaworowski struct mii_data *mii; 72267196661SRafal Jaworowski 72367196661SRafal Jaworowski TSEC_TRANSMIT_LOCK(sc); 72467196661SRafal Jaworowski 72567196661SRafal Jaworowski mii = sc->tsec_mii; 72667196661SRafal Jaworowski mii_pollstat(mii); 72767196661SRafal Jaworowski 72867196661SRafal Jaworowski ifmr->ifm_active = mii->mii_media_active; 72967196661SRafal Jaworowski ifmr->ifm_status = mii->mii_media_status; 73067196661SRafal Jaworowski 73167196661SRafal Jaworowski TSEC_TRANSMIT_UNLOCK(sc); 73267196661SRafal Jaworowski } 73367196661SRafal Jaworowski 73467196661SRafal Jaworowski static int 73567196661SRafal Jaworowski tsec_new_rxbuf(bus_dma_tag_t tag, bus_dmamap_t map, struct mbuf **mbufp, 73667196661SRafal Jaworowski uint32_t *paddr) 73767196661SRafal Jaworowski { 73867196661SRafal Jaworowski struct mbuf *new_mbuf; 73967196661SRafal Jaworowski bus_dma_segment_t seg[1]; 74067196661SRafal Jaworowski int error; 74167196661SRafal Jaworowski int nsegs; 74267196661SRafal Jaworowski 74367196661SRafal Jaworowski KASSERT(mbufp != NULL, ("NULL mbuf pointer!")); 74467196661SRafal Jaworowski 74567196661SRafal Jaworowski new_mbuf = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 74667196661SRafal Jaworowski if (new_mbuf == NULL) 74767196661SRafal Jaworowski return (ENOBUFS); 74867196661SRafal Jaworowski new_mbuf->m_len = new_mbuf->m_pkthdr.len = new_mbuf->m_ext.ext_size; 74967196661SRafal Jaworowski 75067196661SRafal Jaworowski if (*mbufp) { 75167196661SRafal Jaworowski bus_dmamap_sync(tag, map, BUS_DMASYNC_POSTREAD); 75267196661SRafal Jaworowski bus_dmamap_unload(tag, map); 75367196661SRafal Jaworowski } 75467196661SRafal Jaworowski 75567196661SRafal Jaworowski error = bus_dmamap_load_mbuf_sg(tag, map, new_mbuf, seg, &nsegs, 75667196661SRafal Jaworowski BUS_DMA_NOWAIT); 75767196661SRafal Jaworowski KASSERT(nsegs == 1, ("Too many segments returned!")); 75867196661SRafal Jaworowski if (nsegs != 1 || error) 75967196661SRafal Jaworowski panic("tsec_new_rxbuf(): nsegs(%d), error(%d)", nsegs, error); 76067196661SRafal Jaworowski 76167196661SRafal Jaworowski #if 0 76267196661SRafal Jaworowski if (error) { 76367196661SRafal Jaworowski printf("tsec: bus_dmamap_load_mbuf_sg() returned: %d!\n", 76467196661SRafal Jaworowski error); 76567196661SRafal Jaworowski m_freem(new_mbuf); 76667196661SRafal Jaworowski return (ENOBUFS); 76767196661SRafal Jaworowski } 76867196661SRafal Jaworowski #endif 76967196661SRafal Jaworowski 77067196661SRafal Jaworowski #if 0 77167196661SRafal Jaworowski KASSERT(((seg->ds_addr) & (TSEC_RXBUFFER_ALIGNMENT-1)) == 0, 77267196661SRafal Jaworowski ("Wrong alignment of RX buffer!")); 77367196661SRafal Jaworowski #endif 77467196661SRafal Jaworowski bus_dmamap_sync(tag, map, BUS_DMASYNC_PREREAD); 77567196661SRafal Jaworowski 77667196661SRafal Jaworowski (*mbufp) = new_mbuf; 77767196661SRafal Jaworowski (*paddr) = seg->ds_addr; 77867196661SRafal Jaworowski return (0); 77967196661SRafal Jaworowski } 78067196661SRafal Jaworowski 78167196661SRafal Jaworowski static void 78267196661SRafal Jaworowski tsec_map_dma_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error) 78367196661SRafal Jaworowski { 78467196661SRafal Jaworowski u_int32_t *paddr; 78567196661SRafal Jaworowski 78667196661SRafal Jaworowski KASSERT(nseg == 1, ("wrong number of segments, should be 1")); 78767196661SRafal Jaworowski paddr = arg; 78867196661SRafal Jaworowski *paddr = segs->ds_addr; 78967196661SRafal Jaworowski } 79067196661SRafal Jaworowski 79167196661SRafal Jaworowski static int 79267196661SRafal Jaworowski tsec_alloc_dma_desc(device_t dev, bus_dma_tag_t *dtag, bus_dmamap_t *dmap, 79367196661SRafal Jaworowski bus_size_t dsize, void **vaddr, void *raddr, const char *dname) 79467196661SRafal Jaworowski { 79567196661SRafal Jaworowski int error; 79667196661SRafal Jaworowski 79767196661SRafal Jaworowski /* Allocate a busdma tag and DMA safe memory for TX/RX descriptors. */ 79867196661SRafal Jaworowski error = bus_dma_tag_create(NULL, /* parent */ 79967196661SRafal Jaworowski PAGE_SIZE, 0, /* alignment, boundary */ 80067196661SRafal Jaworowski BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 80167196661SRafal Jaworowski BUS_SPACE_MAXADDR, /* highaddr */ 80267196661SRafal Jaworowski NULL, NULL, /* filtfunc, filtfuncarg */ 80367196661SRafal Jaworowski dsize, 1, /* maxsize, nsegments */ 80467196661SRafal Jaworowski dsize, 0, /* maxsegsz, flags */ 80567196661SRafal Jaworowski NULL, NULL, /* lockfunc, lockfuncarg */ 80667196661SRafal Jaworowski dtag); /* dmat */ 80767196661SRafal Jaworowski 80867196661SRafal Jaworowski if (error) { 80967196661SRafal Jaworowski device_printf(dev, "failed to allocate busdma %s tag\n", dname); 81067196661SRafal Jaworowski (*vaddr) = NULL; 81167196661SRafal Jaworowski return (ENXIO); 81267196661SRafal Jaworowski } 81367196661SRafal Jaworowski 81467196661SRafal Jaworowski error = bus_dmamem_alloc(*dtag, vaddr, BUS_DMA_NOWAIT | BUS_DMA_ZERO, 81567196661SRafal Jaworowski dmap); 81667196661SRafal Jaworowski if (error) { 81767196661SRafal Jaworowski device_printf(dev, "failed to allocate %s DMA safe memory\n", 81867196661SRafal Jaworowski dname); 81967196661SRafal Jaworowski bus_dma_tag_destroy(*dtag); 82067196661SRafal Jaworowski (*vaddr) = NULL; 82167196661SRafal Jaworowski return (ENXIO); 82267196661SRafal Jaworowski } 82367196661SRafal Jaworowski 82467196661SRafal Jaworowski error = bus_dmamap_load(*dtag, *dmap, *vaddr, dsize, tsec_map_dma_addr, 82567196661SRafal Jaworowski raddr, BUS_DMA_NOWAIT); 82667196661SRafal Jaworowski if (error) { 82767196661SRafal Jaworowski device_printf(dev, "cannot get address of the %s descriptors\n", 82867196661SRafal Jaworowski dname); 82967196661SRafal Jaworowski bus_dmamem_free(*dtag, *vaddr, *dmap); 83067196661SRafal Jaworowski bus_dma_tag_destroy(*dtag); 83167196661SRafal Jaworowski (*vaddr) = NULL; 83267196661SRafal Jaworowski return (ENXIO); 83367196661SRafal Jaworowski } 83467196661SRafal Jaworowski 83567196661SRafal Jaworowski return (0); 83667196661SRafal Jaworowski } 83767196661SRafal Jaworowski 83867196661SRafal Jaworowski static void 83967196661SRafal Jaworowski tsec_free_dma_desc(bus_dma_tag_t dtag, bus_dmamap_t dmap, void *vaddr) 84067196661SRafal Jaworowski { 84167196661SRafal Jaworowski 84267196661SRafal Jaworowski if (vaddr == NULL) 84367196661SRafal Jaworowski return; 84467196661SRafal Jaworowski 84567196661SRafal Jaworowski /* Unmap descriptors from DMA memory */ 84667196661SRafal Jaworowski bus_dmamap_sync(dtag, dmap, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 84767196661SRafal Jaworowski bus_dmamap_unload(dtag, dmap); 84867196661SRafal Jaworowski 84967196661SRafal Jaworowski /* Free descriptors memory */ 85067196661SRafal Jaworowski bus_dmamem_free(dtag, vaddr, dmap); 85167196661SRafal Jaworowski 85267196661SRafal Jaworowski /* Destroy descriptors tag */ 85367196661SRafal Jaworowski bus_dma_tag_destroy(dtag); 85467196661SRafal Jaworowski } 85567196661SRafal Jaworowski 85667196661SRafal Jaworowski static int 85767196661SRafal Jaworowski tsec_probe(device_t dev) 85867196661SRafal Jaworowski { 85967196661SRafal Jaworowski struct tsec_softc *sc; 86067196661SRafal Jaworowski device_t parent; 86167196661SRafal Jaworowski uintptr_t devtype; 86267196661SRafal Jaworowski int error; 86367196661SRafal Jaworowski uint32_t id; 86467196661SRafal Jaworowski 86567196661SRafal Jaworowski parent = device_get_parent(dev); 86667196661SRafal Jaworowski 86767196661SRafal Jaworowski error = BUS_READ_IVAR(parent, dev, OCPBUS_IVAR_DEVTYPE, &devtype); 86867196661SRafal Jaworowski if (error) 86967196661SRafal Jaworowski return (error); 87067196661SRafal Jaworowski if (devtype != OCPBUS_DEVTYPE_TSEC) 87167196661SRafal Jaworowski return (ENXIO); 87267196661SRafal Jaworowski 87367196661SRafal Jaworowski sc = device_get_softc(dev); 87467196661SRafal Jaworowski 87567196661SRafal Jaworowski sc->sc_rrid = 0; 87667196661SRafal Jaworowski sc->sc_rres = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->sc_rrid, 87767196661SRafal Jaworowski 0ul, ~0ul, TSEC_IO_SIZE, RF_ACTIVE); 87867196661SRafal Jaworowski if (sc->sc_rres == NULL) 87967196661SRafal Jaworowski return (ENXIO); 88067196661SRafal Jaworowski 88167196661SRafal Jaworowski sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres); 88267196661SRafal Jaworowski sc->sc_bas.bst = rman_get_bustag(sc->sc_rres); 88367196661SRafal Jaworowski 88467196661SRafal Jaworowski /* Check that we actually have a TSEC at this address */ 88567196661SRafal Jaworowski id = TSEC_READ(sc, TSEC_REG_ID) | TSEC_READ(sc, TSEC_REG_ID2); 88667196661SRafal Jaworowski 88767196661SRafal Jaworowski bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rrid, sc->sc_rres); 88867196661SRafal Jaworowski 88967196661SRafal Jaworowski if (id == 0) 89067196661SRafal Jaworowski return (ENXIO); 89167196661SRafal Jaworowski 89267196661SRafal Jaworowski device_set_desc(dev, "Three-Speed Ethernet Controller"); 89367196661SRafal Jaworowski return (BUS_PROBE_DEFAULT); 89467196661SRafal Jaworowski } 89567196661SRafal Jaworowski 89667196661SRafal Jaworowski static int 89767196661SRafal Jaworowski tsec_attach(device_t dev) 89867196661SRafal Jaworowski { 89967196661SRafal Jaworowski uint8_t hwaddr[ETHER_ADDR_LEN]; 90067196661SRafal Jaworowski struct tsec_softc *sc; 90167196661SRafal Jaworowski struct ifnet *ifp; 90267196661SRafal Jaworowski bus_dmamap_t *map_ptr; 90367196661SRafal Jaworowski bus_dmamap_t **map_pptr; 90467196661SRafal Jaworowski int error = 0; 90567196661SRafal Jaworowski int i; 90667196661SRafal Jaworowski 90767196661SRafal Jaworowski sc = device_get_softc(dev); 90867196661SRafal Jaworowski sc->dev = dev; 90967196661SRafal Jaworowski 91067196661SRafal Jaworowski if (device_get_unit(dev) == 0) 91167196661SRafal Jaworowski tsec0_sc = sc; /* XXX */ 91267196661SRafal Jaworowski 91367196661SRafal Jaworowski callout_init(&sc->tsec_tick_ch, 1); 91467196661SRafal Jaworowski mtx_init(&sc->transmit_lock, device_get_nameunit(dev), "TSEC TX lock", 91567196661SRafal Jaworowski MTX_DEF); 91667196661SRafal Jaworowski mtx_init(&sc->receive_lock, device_get_nameunit(dev), "TSEC RX lock", 91767196661SRafal Jaworowski MTX_DEF); 91867196661SRafal Jaworowski 91967196661SRafal Jaworowski /* Reset all TSEC counters */ 92067196661SRafal Jaworowski TSEC_TX_RX_COUNTERS_INIT(sc); 92167196661SRafal Jaworowski 92267196661SRafal Jaworowski /* Allocate IO memory for TSEC registers */ 92367196661SRafal Jaworowski sc->sc_rrid = 0; 92467196661SRafal Jaworowski sc->sc_rres = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->sc_rrid, 92567196661SRafal Jaworowski 0ul, ~0ul, TSEC_IO_SIZE, RF_ACTIVE); 92667196661SRafal Jaworowski if (sc->sc_rres == NULL) { 92767196661SRafal Jaworowski device_printf(dev, "could not allocate IO memory range!\n"); 92867196661SRafal Jaworowski tsec_detach(dev); 92967196661SRafal Jaworowski return (ENXIO); 93067196661SRafal Jaworowski } 93167196661SRafal Jaworowski sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres); 93267196661SRafal Jaworowski sc->sc_bas.bst = rman_get_bustag(sc->sc_rres); 93367196661SRafal Jaworowski 93467196661SRafal Jaworowski /* Stop DMA engine if enabled by firmware */ 93567196661SRafal Jaworowski tsec_dma_ctl(sc, 0); 93667196661SRafal Jaworowski 93767196661SRafal Jaworowski /* Reset MAC */ 93867196661SRafal Jaworowski tsec_reset_mac(sc); 93967196661SRafal Jaworowski 94067196661SRafal Jaworowski /* Disable interrupts for now */ 94167196661SRafal Jaworowski tsec_intrs_ctl(sc, 0); 94267196661SRafal Jaworowski 94367196661SRafal Jaworowski /* Allocate a busdma tag and DMA safe memory for TX descriptors. */ 94467196661SRafal Jaworowski error = tsec_alloc_dma_desc(dev, &sc->tsec_tx_dtag, &sc->tsec_tx_dmap, 94567196661SRafal Jaworowski sizeof(*sc->tsec_tx_vaddr) * TSEC_TX_NUM_DESC, 94667196661SRafal Jaworowski (void **)&sc->tsec_tx_vaddr, &sc->tsec_tx_raddr, "TX"); 94767196661SRafal Jaworowski if (error) { 94867196661SRafal Jaworowski tsec_detach(dev); 94967196661SRafal Jaworowski return (ENXIO); 95067196661SRafal Jaworowski } 95167196661SRafal Jaworowski 95267196661SRafal Jaworowski /* Allocate a busdma tag and DMA safe memory for RX descriptors. */ 95367196661SRafal Jaworowski error = tsec_alloc_dma_desc(dev, &sc->tsec_rx_dtag, &sc->tsec_rx_dmap, 95467196661SRafal Jaworowski sizeof(*sc->tsec_rx_vaddr) * TSEC_RX_NUM_DESC, 95567196661SRafal Jaworowski (void **)&sc->tsec_rx_vaddr, &sc->tsec_rx_raddr, "RX"); 95667196661SRafal Jaworowski if (error) { 95767196661SRafal Jaworowski tsec_detach(dev); 95867196661SRafal Jaworowski return (ENXIO); 95967196661SRafal Jaworowski } 96067196661SRafal Jaworowski 96167196661SRafal Jaworowski /* Allocate a busdma tag for TX mbufs. */ 96267196661SRafal Jaworowski error = bus_dma_tag_create(NULL, /* parent */ 96367196661SRafal Jaworowski TSEC_TXBUFFER_ALIGNMENT, 0, /* alignment, boundary */ 96467196661SRafal Jaworowski BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 96567196661SRafal Jaworowski BUS_SPACE_MAXADDR, /* highaddr */ 96667196661SRafal Jaworowski NULL, NULL, /* filtfunc, filtfuncarg */ 96767196661SRafal Jaworowski MCLBYTES * (TSEC_TX_NUM_DESC - 1), /* maxsize */ 96867196661SRafal Jaworowski TSEC_TX_NUM_DESC - 1, /* nsegments */ 96967196661SRafal Jaworowski MCLBYTES, 0, /* maxsegsz, flags */ 97067196661SRafal Jaworowski NULL, NULL, /* lockfunc, lockfuncarg */ 97167196661SRafal Jaworowski &sc->tsec_tx_mtag); /* dmat */ 97267196661SRafal Jaworowski if (error) { 97367196661SRafal Jaworowski device_printf(dev, "failed to allocate busdma tag(tx mbufs)\n"); 97467196661SRafal Jaworowski tsec_detach(dev); 97567196661SRafal Jaworowski return (ENXIO); 97667196661SRafal Jaworowski } 97767196661SRafal Jaworowski 97867196661SRafal Jaworowski /* Allocate a busdma tag for RX mbufs. */ 97967196661SRafal Jaworowski error = bus_dma_tag_create(NULL, /* parent */ 98067196661SRafal Jaworowski TSEC_RXBUFFER_ALIGNMENT, 0, /* alignment, boundary */ 98167196661SRafal Jaworowski BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 98267196661SRafal Jaworowski BUS_SPACE_MAXADDR, /* highaddr */ 98367196661SRafal Jaworowski NULL, NULL, /* filtfunc, filtfuncarg */ 98467196661SRafal Jaworowski MCLBYTES, /* maxsize */ 98567196661SRafal Jaworowski 1, /* nsegments */ 98667196661SRafal Jaworowski MCLBYTES, 0, /* maxsegsz, flags */ 98767196661SRafal Jaworowski NULL, NULL, /* lockfunc, lockfuncarg */ 98867196661SRafal Jaworowski &sc->tsec_rx_mtag); /* dmat */ 98967196661SRafal Jaworowski if (error) { 99067196661SRafal Jaworowski device_printf(dev, "failed to allocate busdma tag(rx mbufs)\n"); 99167196661SRafal Jaworowski tsec_detach(dev); 99267196661SRafal Jaworowski return (ENXIO); 99367196661SRafal Jaworowski } 99467196661SRafal Jaworowski 99567196661SRafal Jaworowski /* Create TX busdma maps */ 99667196661SRafal Jaworowski map_ptr = sc->tx_map_data; 99767196661SRafal Jaworowski map_pptr = sc->tx_map_unused_data; 99867196661SRafal Jaworowski 99967196661SRafal Jaworowski for (i = 0; i < TSEC_TX_NUM_DESC; i++) { 100067196661SRafal Jaworowski map_pptr[i] = &map_ptr[i]; 100167196661SRafal Jaworowski error = bus_dmamap_create(sc->tsec_tx_mtag, 0, 100267196661SRafal Jaworowski map_pptr[i]); 100367196661SRafal Jaworowski if (error) { 100467196661SRafal Jaworowski device_printf(dev, "failed to init TX ring\n"); 100567196661SRafal Jaworowski tsec_detach(dev); 100667196661SRafal Jaworowski return (ENXIO); 100767196661SRafal Jaworowski } 100867196661SRafal Jaworowski } 100967196661SRafal Jaworowski 101067196661SRafal Jaworowski /* Create RX busdma maps and zero mbuf handlers */ 101167196661SRafal Jaworowski for (i = 0; i < TSEC_RX_NUM_DESC; i++) { 101267196661SRafal Jaworowski error = bus_dmamap_create(sc->tsec_rx_mtag, 0, 101367196661SRafal Jaworowski &sc->rx_data[i].map); 101467196661SRafal Jaworowski if (error) { 101567196661SRafal Jaworowski device_printf(dev, "failed to init RX ring\n"); 101667196661SRafal Jaworowski tsec_detach(dev); 101767196661SRafal Jaworowski return (ENXIO); 101867196661SRafal Jaworowski } 101967196661SRafal Jaworowski sc->rx_data[i].mbuf = NULL; 102067196661SRafal Jaworowski } 102167196661SRafal Jaworowski 102267196661SRafal Jaworowski /* Create mbufs for RX buffers */ 102367196661SRafal Jaworowski for (i = 0; i < TSEC_RX_NUM_DESC; i++) { 102467196661SRafal Jaworowski error = tsec_new_rxbuf(sc->tsec_rx_mtag, sc->rx_data[i].map, 102567196661SRafal Jaworowski &sc->rx_data[i].mbuf, &sc->rx_data[i].paddr); 102667196661SRafal Jaworowski if (error) { 102767196661SRafal Jaworowski device_printf(dev, "can't load rx DMA map %d, error = " 102867196661SRafal Jaworowski "%d\n", i, error); 102967196661SRafal Jaworowski tsec_detach(dev); 103067196661SRafal Jaworowski return (error); 103167196661SRafal Jaworowski } 103267196661SRafal Jaworowski } 103367196661SRafal Jaworowski 103467196661SRafal Jaworowski /* Create network interface for upper layers */ 103567196661SRafal Jaworowski ifp = sc->tsec_ifp = if_alloc(IFT_ETHER); 103667196661SRafal Jaworowski if (ifp == NULL) { 103767196661SRafal Jaworowski device_printf(dev, "if_alloc() failed\n"); 103867196661SRafal Jaworowski tsec_detach(dev); 103967196661SRafal Jaworowski return (ENOMEM); 104067196661SRafal Jaworowski } 104167196661SRafal Jaworowski 104267196661SRafal Jaworowski ifp->if_softc = sc; 104367196661SRafal Jaworowski if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 104467196661SRafal Jaworowski ifp->if_mtu = ETHERMTU; 104567196661SRafal Jaworowski ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST; 104667196661SRafal Jaworowski ifp->if_init = tsec_init; 104767196661SRafal Jaworowski ifp->if_start = tsec_start; 104867196661SRafal Jaworowski ifp->if_watchdog = tsec_watchdog; 104967196661SRafal Jaworowski ifp->if_ioctl = tsec_ioctl; 105067196661SRafal Jaworowski 105167196661SRafal Jaworowski IFQ_SET_MAXLEN(&ifp->if_snd, TSEC_TX_NUM_DESC - 1); 105267196661SRafal Jaworowski ifp->if_snd.ifq_drv_maxlen = TSEC_TX_NUM_DESC - 1; 105367196661SRafal Jaworowski IFQ_SET_READY(&ifp->if_snd); 105467196661SRafal Jaworowski 105567196661SRafal Jaworowski /* XXX No special features of TSEC are supported currently */ 105667196661SRafal Jaworowski ifp->if_capabilities = 0; 105767196661SRafal Jaworowski ifp->if_capenable = ifp->if_capabilities; 105867196661SRafal Jaworowski 105967196661SRafal Jaworowski /* Probe PHY(s) */ 106067196661SRafal Jaworowski error = mii_phy_probe(dev, &sc->tsec_miibus, tsec_ifmedia_upd, 106167196661SRafal Jaworowski tsec_ifmedia_sts); 106267196661SRafal Jaworowski if (error) { 106367196661SRafal Jaworowski device_printf(dev, "MII failed to find PHY!\n"); 106467196661SRafal Jaworowski if_free(ifp); 106567196661SRafal Jaworowski sc->tsec_ifp = NULL; 106667196661SRafal Jaworowski tsec_detach(dev); 106767196661SRafal Jaworowski return (error); 106867196661SRafal Jaworowski } 106967196661SRafal Jaworowski sc->tsec_mii = device_get_softc(sc->tsec_miibus); 107067196661SRafal Jaworowski 107167196661SRafal Jaworowski tsec_get_hwaddr(sc, hwaddr); 107267196661SRafal Jaworowski ether_ifattach(ifp, hwaddr); 107367196661SRafal Jaworowski 107467196661SRafal Jaworowski /* Interrupts configuration (TX/RX/ERR) */ 107567196661SRafal Jaworowski sc->sc_transmit_irid = OCP_TSEC_RID_TXIRQ; 107667196661SRafal Jaworowski error = tsec_setup_intr(dev, &sc->sc_transmit_ires, 107767196661SRafal Jaworowski &sc->sc_transmit_ihand, &sc->sc_transmit_irid, 107867196661SRafal Jaworowski tsec_transmit_intr, "TX"); 107967196661SRafal Jaworowski if (error) { 108067196661SRafal Jaworowski tsec_detach(dev); 108167196661SRafal Jaworowski return (error); 108267196661SRafal Jaworowski } 108367196661SRafal Jaworowski 108467196661SRafal Jaworowski sc->sc_receive_irid = OCP_TSEC_RID_RXIRQ; 108567196661SRafal Jaworowski error = tsec_setup_intr(dev, &sc->sc_receive_ires, 108667196661SRafal Jaworowski &sc->sc_receive_ihand, &sc->sc_receive_irid, 108767196661SRafal Jaworowski tsec_receive_intr, "RX"); 108867196661SRafal Jaworowski if (error) { 108967196661SRafal Jaworowski tsec_detach(dev); 109067196661SRafal Jaworowski return (error); 109167196661SRafal Jaworowski } 109267196661SRafal Jaworowski 109367196661SRafal Jaworowski sc->sc_error_irid = OCP_TSEC_RID_ERRIRQ; 109467196661SRafal Jaworowski error = tsec_setup_intr(dev, &sc->sc_error_ires, 109567196661SRafal Jaworowski &sc->sc_error_ihand, &sc->sc_error_irid, 109667196661SRafal Jaworowski tsec_error_intr, "ERR"); 109767196661SRafal Jaworowski if (error) { 109867196661SRafal Jaworowski tsec_detach(dev); 109967196661SRafal Jaworowski return (error); 110067196661SRafal Jaworowski } 110167196661SRafal Jaworowski 110267196661SRafal Jaworowski return (0); 110367196661SRafal Jaworowski } 110467196661SRafal Jaworowski 110567196661SRafal Jaworowski static int 110667196661SRafal Jaworowski tsec_setup_intr(device_t dev, struct resource **ires, void **ihand, int *irid, 110767196661SRafal Jaworowski driver_intr_t handler, const char *iname) 110867196661SRafal Jaworowski { 110967196661SRafal Jaworowski struct tsec_softc *sc; 111067196661SRafal Jaworowski int error; 111167196661SRafal Jaworowski 111267196661SRafal Jaworowski sc = device_get_softc(dev); 111367196661SRafal Jaworowski 111467196661SRafal Jaworowski (*ires) = bus_alloc_resource_any(dev, SYS_RES_IRQ, irid, RF_ACTIVE); 111567196661SRafal Jaworowski if ((*ires) == NULL) { 111667196661SRafal Jaworowski device_printf(dev, "could not allocate %s IRQ\n", iname); 111767196661SRafal Jaworowski return (ENXIO); 111867196661SRafal Jaworowski } 111967196661SRafal Jaworowski error = bus_setup_intr(dev, *ires, INTR_TYPE_NET | INTR_MPSAFE, 112067196661SRafal Jaworowski NULL, handler, sc, ihand); 112167196661SRafal Jaworowski if (error) { 112267196661SRafal Jaworowski device_printf(dev, "failed to set up %s IRQ\n", iname); 112367196661SRafal Jaworowski if (bus_release_resource(dev, SYS_RES_IRQ, *irid, *ires)) 112467196661SRafal Jaworowski device_printf(dev, "could not release %s IRQ\n", iname); 112567196661SRafal Jaworowski (*ires) = NULL; 112667196661SRafal Jaworowski return (error); 112767196661SRafal Jaworowski } 112867196661SRafal Jaworowski return (0); 112967196661SRafal Jaworowski } 113067196661SRafal Jaworowski 113167196661SRafal Jaworowski static void 113267196661SRafal Jaworowski tsec_release_intr(device_t dev, struct resource *ires, void *ihand, int irid, 113367196661SRafal Jaworowski const char *iname) 113467196661SRafal Jaworowski { 113567196661SRafal Jaworowski int error; 113667196661SRafal Jaworowski 113767196661SRafal Jaworowski if (ires == NULL) 113867196661SRafal Jaworowski return; 113967196661SRafal Jaworowski 114067196661SRafal Jaworowski error = bus_teardown_intr(dev, ires, ihand); 114167196661SRafal Jaworowski if (error) 114267196661SRafal Jaworowski device_printf(dev, "bus_teardown_intr() failed for %s intr" 114367196661SRafal Jaworowski ", error %d\n", iname, error); 114467196661SRafal Jaworowski 114567196661SRafal Jaworowski error = bus_release_resource(dev, SYS_RES_IRQ, irid, ires); 114667196661SRafal Jaworowski if (error) 114767196661SRafal Jaworowski device_printf(dev, "bus_release_resource() failed for %s intr" 114867196661SRafal Jaworowski ", error %d\n", iname, error); 114967196661SRafal Jaworowski } 115067196661SRafal Jaworowski 115167196661SRafal Jaworowski static void 115267196661SRafal Jaworowski tsec_free_dma(struct tsec_softc *sc) 115367196661SRafal Jaworowski { 115467196661SRafal Jaworowski int i; 115567196661SRafal Jaworowski 115667196661SRafal Jaworowski /* Free TX maps */ 115767196661SRafal Jaworowski for (i = 0; i < TSEC_TX_NUM_DESC; i++) 115867196661SRafal Jaworowski if (sc->tx_map_data[i] != NULL) 115967196661SRafal Jaworowski bus_dmamap_destroy(sc->tsec_tx_mtag, 116067196661SRafal Jaworowski sc->tx_map_data[i]); 116167196661SRafal Jaworowski /* Destroy tag for Tx mbufs */ 116267196661SRafal Jaworowski bus_dma_tag_destroy(sc->tsec_tx_mtag); 116367196661SRafal Jaworowski 116467196661SRafal Jaworowski /* Free RX mbufs and maps */ 116567196661SRafal Jaworowski for (i = 0; i < TSEC_RX_NUM_DESC; i++) { 116667196661SRafal Jaworowski if (sc->rx_data[i].mbuf) { 116767196661SRafal Jaworowski /* Unload buffer from DMA */ 116867196661SRafal Jaworowski bus_dmamap_sync(sc->tsec_rx_mtag, sc->rx_data[i].map, 116967196661SRafal Jaworowski BUS_DMASYNC_POSTREAD); 117067196661SRafal Jaworowski bus_dmamap_unload(sc->tsec_rx_mtag, sc->rx_data[i].map); 117167196661SRafal Jaworowski 117267196661SRafal Jaworowski /* Free buffer */ 117367196661SRafal Jaworowski m_freem(sc->rx_data[i].mbuf); 117467196661SRafal Jaworowski } 117567196661SRafal Jaworowski /* Destroy map for this buffer */ 117667196661SRafal Jaworowski if (sc->rx_data[i].map != NULL) 117767196661SRafal Jaworowski bus_dmamap_destroy(sc->tsec_rx_mtag, 117867196661SRafal Jaworowski sc->rx_data[i].map); 117967196661SRafal Jaworowski } 118067196661SRafal Jaworowski /* Destroy tag for Rx mbufs */ 118167196661SRafal Jaworowski bus_dma_tag_destroy(sc->tsec_rx_mtag); 118267196661SRafal Jaworowski 118367196661SRafal Jaworowski /* Unload TX/RX descriptors */ 118467196661SRafal Jaworowski tsec_free_dma_desc(sc->tsec_tx_dtag, sc->tsec_tx_dmap, 118567196661SRafal Jaworowski sc->tsec_tx_vaddr); 118667196661SRafal Jaworowski tsec_free_dma_desc(sc->tsec_rx_dtag, sc->tsec_rx_dmap, 118767196661SRafal Jaworowski sc->tsec_rx_vaddr); 118867196661SRafal Jaworowski } 118967196661SRafal Jaworowski 119067196661SRafal Jaworowski static int 119167196661SRafal Jaworowski tsec_detach(device_t dev) 119267196661SRafal Jaworowski { 119367196661SRafal Jaworowski struct tsec_softc *sc; 119467196661SRafal Jaworowski int error; 119567196661SRafal Jaworowski 119667196661SRafal Jaworowski sc = device_get_softc(dev); 119767196661SRafal Jaworowski 119867196661SRafal Jaworowski /* Stop TSEC controller and free TX queue */ 119967196661SRafal Jaworowski if (sc->sc_rres && sc->tsec_ifp) 120067196661SRafal Jaworowski tsec_shutdown(dev); 120167196661SRafal Jaworowski 120267196661SRafal Jaworowski /* Wait for stopping TSEC ticks */ 120367196661SRafal Jaworowski callout_drain(&sc->tsec_tick_ch); 120467196661SRafal Jaworowski 120567196661SRafal Jaworowski /* Stop and release all interrupts */ 120667196661SRafal Jaworowski tsec_release_intr(dev, sc->sc_transmit_ires, sc->sc_transmit_ihand, 120767196661SRafal Jaworowski sc->sc_transmit_irid, "TX"); 120867196661SRafal Jaworowski tsec_release_intr(dev, sc->sc_receive_ires, sc->sc_receive_ihand, 120967196661SRafal Jaworowski sc->sc_receive_irid, "RX"); 121067196661SRafal Jaworowski tsec_release_intr(dev, sc->sc_error_ires, sc->sc_error_ihand, 121167196661SRafal Jaworowski sc->sc_error_irid, "ERR"); 121267196661SRafal Jaworowski 121367196661SRafal Jaworowski /* Detach network interface */ 121467196661SRafal Jaworowski if (sc->tsec_ifp) { 121567196661SRafal Jaworowski ether_ifdetach(sc->tsec_ifp); 121667196661SRafal Jaworowski if_free(sc->tsec_ifp); 121767196661SRafal Jaworowski sc->tsec_ifp = NULL; 121867196661SRafal Jaworowski } 121967196661SRafal Jaworowski 122067196661SRafal Jaworowski /* Free DMA resources */ 122167196661SRafal Jaworowski tsec_free_dma(sc); 122267196661SRafal Jaworowski 122367196661SRafal Jaworowski /* Free IO memory handler */ 122467196661SRafal Jaworowski if (sc->sc_rres) { 122567196661SRafal Jaworowski error = bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rrid, 122667196661SRafal Jaworowski sc->sc_rres); 122767196661SRafal Jaworowski if (error) 122867196661SRafal Jaworowski device_printf(dev, "bus_release_resource() failed for" 122967196661SRafal Jaworowski " IO memory, error %d\n", error); 123067196661SRafal Jaworowski } 123167196661SRafal Jaworowski 123267196661SRafal Jaworowski /* Destroy locks */ 123367196661SRafal Jaworowski mtx_destroy(&sc->receive_lock); 123467196661SRafal Jaworowski mtx_destroy(&sc->transmit_lock); 123567196661SRafal Jaworowski return (0); 123667196661SRafal Jaworowski } 123767196661SRafal Jaworowski 123867196661SRafal Jaworowski static void 123967196661SRafal Jaworowski tsec_shutdown(device_t dev) 124067196661SRafal Jaworowski { 124167196661SRafal Jaworowski struct tsec_softc *sc; 124267196661SRafal Jaworowski 124367196661SRafal Jaworowski sc = device_get_softc(dev); 124467196661SRafal Jaworowski 124567196661SRafal Jaworowski TSEC_GLOBAL_LOCK(sc); 124667196661SRafal Jaworowski tsec_stop(sc); 124767196661SRafal Jaworowski TSEC_GLOBAL_UNLOCK(sc); 124867196661SRafal Jaworowski } 124967196661SRafal Jaworowski 125067196661SRafal Jaworowski static int 125167196661SRafal Jaworowski tsec_suspend(device_t dev) 125267196661SRafal Jaworowski { 125367196661SRafal Jaworowski 125467196661SRafal Jaworowski /* TODO not implemented! */ 125567196661SRafal Jaworowski return (ENODEV); 125667196661SRafal Jaworowski } 125767196661SRafal Jaworowski 125867196661SRafal Jaworowski static int 125967196661SRafal Jaworowski tsec_resume(device_t dev) 126067196661SRafal Jaworowski { 126167196661SRafal Jaworowski 126267196661SRafal Jaworowski /* TODO not implemented! */ 126367196661SRafal Jaworowski return (ENODEV); 126467196661SRafal Jaworowski } 126567196661SRafal Jaworowski 126667196661SRafal Jaworowski static void 126767196661SRafal Jaworowski tsec_stop(struct tsec_softc *sc) 126867196661SRafal Jaworowski { 126967196661SRafal Jaworowski struct ifnet *ifp; 127067196661SRafal Jaworowski struct mbuf *m0; 127167196661SRafal Jaworowski bus_dmamap_t *mapp; 127267196661SRafal Jaworowski uint32_t tmpval; 127367196661SRafal Jaworowski 127467196661SRafal Jaworowski TSEC_GLOBAL_LOCK_ASSERT(sc); 127567196661SRafal Jaworowski 127667196661SRafal Jaworowski ifp = sc->tsec_ifp; 127767196661SRafal Jaworowski 127867196661SRafal Jaworowski /* Stop PHY tick engine */ 127967196661SRafal Jaworowski callout_stop(&sc->tsec_tick_ch); 128067196661SRafal Jaworowski 128167196661SRafal Jaworowski /* Disable interface and watchdog timer */ 128267196661SRafal Jaworowski ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 128367196661SRafal Jaworowski ifp->if_timer = 0; 128467196661SRafal Jaworowski 128567196661SRafal Jaworowski /* Disable all interrupts and stop DMA */ 128667196661SRafal Jaworowski tsec_intrs_ctl(sc, 0); 128767196661SRafal Jaworowski tsec_dma_ctl(sc, 0); 128867196661SRafal Jaworowski 128967196661SRafal Jaworowski /* Remove pending data from TX queue */ 129067196661SRafal Jaworowski while (!TSEC_EMPTYQ_TX_MBUF(sc)) { 129167196661SRafal Jaworowski m0 = TSEC_GET_TX_MBUF(sc); 129267196661SRafal Jaworowski mapp = TSEC_GET_TX_MAP(sc); 129367196661SRafal Jaworowski 129467196661SRafal Jaworowski bus_dmamap_sync(sc->tsec_tx_mtag, *mapp, BUS_DMASYNC_POSTWRITE); 129567196661SRafal Jaworowski bus_dmamap_unload(sc->tsec_tx_mtag, *mapp); 129667196661SRafal Jaworowski 129767196661SRafal Jaworowski TSEC_FREE_TX_MAP(sc, mapp); 129867196661SRafal Jaworowski m_freem(m0); 129967196661SRafal Jaworowski } 130067196661SRafal Jaworowski 130167196661SRafal Jaworowski /* Disable Rx and Tx */ 130267196661SRafal Jaworowski tmpval = TSEC_READ(sc, TSEC_REG_MACCFG1); 130367196661SRafal Jaworowski tmpval &= ~(TSEC_MACCFG1_RX_EN | TSEC_MACCFG1_TX_EN); 130467196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_MACCFG1, tmpval); 130567196661SRafal Jaworowski DELAY(10); 130667196661SRafal Jaworowski } 130767196661SRafal Jaworowski 130867196661SRafal Jaworowski static void 130967196661SRafal Jaworowski tsec_receive_intr(void *arg) 131067196661SRafal Jaworowski { 131167196661SRafal Jaworowski struct mbuf *rcv_mbufs[TSEC_RX_NUM_DESC]; 131267196661SRafal Jaworowski struct tsec_softc *sc = arg; 131367196661SRafal Jaworowski struct tsec_desc *rx_desc; 131467196661SRafal Jaworowski struct ifnet *ifp; 131567196661SRafal Jaworowski struct rx_data_type *rx_data; 131667196661SRafal Jaworowski struct mbuf *m; 131767196661SRafal Jaworowski device_t dev; 131867196661SRafal Jaworowski uint32_t i; 131967196661SRafal Jaworowski int count; 132067196661SRafal Jaworowski int c1 = 0; 132167196661SRafal Jaworowski int c2; 132267196661SRafal Jaworowski uint16_t flags; 132367196661SRafal Jaworowski uint16_t length; 132467196661SRafal Jaworowski 132567196661SRafal Jaworowski ifp = sc->tsec_ifp; 132667196661SRafal Jaworowski rx_data = sc->rx_data; 132767196661SRafal Jaworowski dev = sc->dev; 132867196661SRafal Jaworowski 132967196661SRafal Jaworowski /* Confirm the interrupt was received by driver */ 133067196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_IEVENT, TSEC_IEVENT_RXB | TSEC_IEVENT_RXF); 133167196661SRafal Jaworowski 133267196661SRafal Jaworowski TSEC_RECEIVE_LOCK(sc); 133367196661SRafal Jaworowski 133467196661SRafal Jaworowski bus_dmamap_sync(sc->tsec_rx_dtag, sc->tsec_rx_dmap, BUS_DMASYNC_POSTREAD | 133567196661SRafal Jaworowski BUS_DMASYNC_POSTWRITE); 133667196661SRafal Jaworowski 133767196661SRafal Jaworowski for (count = 0; /* count < TSEC_RX_NUM_DESC */; count++) { 133867196661SRafal Jaworowski rx_desc = TSEC_GET_CUR_RX_DESC(sc); 133967196661SRafal Jaworowski flags = rx_desc->flags; 134067196661SRafal Jaworowski 134167196661SRafal Jaworowski /* Check if there is anything to receive */ 134267196661SRafal Jaworowski if ((flags & TSEC_RXBD_E) || (count >= TSEC_RX_NUM_DESC)) { 134367196661SRafal Jaworowski /* 134467196661SRafal Jaworowski * Avoid generating another interrupt 134567196661SRafal Jaworowski */ 134667196661SRafal Jaworowski if (flags & TSEC_RXBD_E) 134767196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_IEVENT, 134867196661SRafal Jaworowski TSEC_IEVENT_RXB | TSEC_IEVENT_RXF); 134967196661SRafal Jaworowski /* 135067196661SRafal Jaworowski * We didn't consume current descriptor and have to 135167196661SRafal Jaworowski * return it to the queue 135267196661SRafal Jaworowski */ 135367196661SRafal Jaworowski TSEC_BACK_CUR_RX_DESC(sc); 135467196661SRafal Jaworowski break; 135567196661SRafal Jaworowski } 135667196661SRafal Jaworowski 135767196661SRafal Jaworowski if (flags & (TSEC_RXBD_LG | TSEC_RXBD_SH | TSEC_RXBD_NO | 135867196661SRafal Jaworowski TSEC_RXBD_CR | TSEC_RXBD_OV | TSEC_RXBD_TR)) { 135967196661SRafal Jaworowski rx_desc->length = 0; 136067196661SRafal Jaworowski rx_desc->flags = (rx_desc->flags & 136167196661SRafal Jaworowski ~TSEC_RXBD_ZEROONINIT) | TSEC_RXBD_E | TSEC_RXBD_I; 136267196661SRafal Jaworowski continue; 136367196661SRafal Jaworowski } 136467196661SRafal Jaworowski 136567196661SRafal Jaworowski if ((flags & TSEC_RXBD_L) == 0) 136667196661SRafal Jaworowski device_printf(dev, "buf is not the last in frame!\n"); 136767196661SRafal Jaworowski 136867196661SRafal Jaworowski /* Ok... process frame */ 136967196661SRafal Jaworowski length = rx_desc->length - ETHER_CRC_LEN; 137067196661SRafal Jaworowski i = TSEC_GET_CUR_RX_DESC_CNT(sc); 137167196661SRafal Jaworowski 137267196661SRafal Jaworowski m = rx_data[i].mbuf; 137367196661SRafal Jaworowski 137467196661SRafal Jaworowski if (tsec_new_rxbuf(sc->tsec_rx_mtag, rx_data[i].map, 137567196661SRafal Jaworowski &rx_data[i].mbuf, &rx_data[i].paddr)) { 137667196661SRafal Jaworowski ifp->if_ierrors++; 137767196661SRafal Jaworowski continue; 137867196661SRafal Jaworowski } 137967196661SRafal Jaworowski /* Attach new buffer to descriptor, and clear flags */ 138067196661SRafal Jaworowski rx_desc->bufptr = rx_data[i].paddr; 138167196661SRafal Jaworowski rx_desc->length = 0; 138267196661SRafal Jaworowski rx_desc->flags = (rx_desc->flags & ~TSEC_RXBD_ZEROONINIT) | 138367196661SRafal Jaworowski TSEC_RXBD_E | TSEC_RXBD_I; 138467196661SRafal Jaworowski 138567196661SRafal Jaworowski /* Prepare buffer for upper layers */ 138667196661SRafal Jaworowski m->m_pkthdr.rcvif = ifp; 138767196661SRafal Jaworowski m->m_pkthdr.len = m->m_len = length; 138867196661SRafal Jaworowski 138967196661SRafal Jaworowski /* Save it for push */ 139067196661SRafal Jaworowski rcv_mbufs[c1++] = m; 139167196661SRafal Jaworowski } 139267196661SRafal Jaworowski 139367196661SRafal Jaworowski bus_dmamap_sync(sc->tsec_rx_dtag, sc->tsec_rx_dmap, 139467196661SRafal Jaworowski BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 139567196661SRafal Jaworowski 139667196661SRafal Jaworowski TSEC_RECEIVE_UNLOCK(sc); 139767196661SRafal Jaworowski 139867196661SRafal Jaworowski /* Push it now */ 139967196661SRafal Jaworowski for (c2 = 0; c2 < c1; c2++) 140067196661SRafal Jaworowski (*ifp->if_input)(ifp, rcv_mbufs[c2]); 140167196661SRafal Jaworowski } 140267196661SRafal Jaworowski 140367196661SRafal Jaworowski static void 140467196661SRafal Jaworowski tsec_transmit_intr(void *arg) 140567196661SRafal Jaworowski { 140667196661SRafal Jaworowski struct tsec_softc *sc = arg; 140767196661SRafal Jaworowski struct tsec_desc *tx_desc; 140867196661SRafal Jaworowski struct ifnet *ifp; 140967196661SRafal Jaworowski struct mbuf *m0; 141067196661SRafal Jaworowski bus_dmamap_t *mapp; 141167196661SRafal Jaworowski int send = 0; 141267196661SRafal Jaworowski 141367196661SRafal Jaworowski ifp = sc->tsec_ifp; 141467196661SRafal Jaworowski 141567196661SRafal Jaworowski /* Confirm the interrupt was received by driver */ 141667196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_IEVENT, TSEC_IEVENT_TXB | TSEC_IEVENT_TXF); 141767196661SRafal Jaworowski 141867196661SRafal Jaworowski TSEC_TRANSMIT_LOCK(sc); 141967196661SRafal Jaworowski 142067196661SRafal Jaworowski /* Update collision statistics */ 142167196661SRafal Jaworowski ifp->if_collisions += TSEC_READ(sc, TSEC_REG_MON_TNCL); 142267196661SRafal Jaworowski 142367196661SRafal Jaworowski /* Reset collision counters in hardware */ 142467196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_MON_TSCL, 0); 142567196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_MON_TMCL, 0); 142667196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_MON_TLCL, 0); 142767196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_MON_TXCL, 0); 142867196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_MON_TNCL, 0); 142967196661SRafal Jaworowski 143067196661SRafal Jaworowski bus_dmamap_sync(sc->tsec_tx_dtag, sc->tsec_tx_dmap, BUS_DMASYNC_POSTREAD | 143167196661SRafal Jaworowski BUS_DMASYNC_POSTWRITE); 143267196661SRafal Jaworowski 143367196661SRafal Jaworowski while (TSEC_CUR_DIFF_DIRTY_TX_DESC(sc)) { 143467196661SRafal Jaworowski tx_desc = TSEC_GET_DIRTY_TX_DESC(sc); 143567196661SRafal Jaworowski if (tx_desc->flags & TSEC_TXBD_R) { 143667196661SRafal Jaworowski TSEC_BACK_DIRTY_TX_DESC(sc); 143767196661SRafal Jaworowski break; 143867196661SRafal Jaworowski } 143967196661SRafal Jaworowski 144067196661SRafal Jaworowski if ((tx_desc->flags & TSEC_TXBD_L) == 0) 144167196661SRafal Jaworowski continue; 144267196661SRafal Jaworowski 144367196661SRafal Jaworowski /* 144467196661SRafal Jaworowski * This is the last buf in this packet, so unmap and free it. 144567196661SRafal Jaworowski */ 144667196661SRafal Jaworowski m0 = TSEC_GET_TX_MBUF(sc); 144767196661SRafal Jaworowski mapp = TSEC_GET_TX_MAP(sc); 144867196661SRafal Jaworowski 144967196661SRafal Jaworowski bus_dmamap_sync(sc->tsec_tx_mtag, *mapp, BUS_DMASYNC_POSTWRITE); 145067196661SRafal Jaworowski bus_dmamap_unload(sc->tsec_tx_mtag, *mapp); 145167196661SRafal Jaworowski 145267196661SRafal Jaworowski TSEC_FREE_TX_MAP(sc, mapp); 145367196661SRafal Jaworowski m_freem(m0); 145467196661SRafal Jaworowski 145567196661SRafal Jaworowski ifp->if_opackets++; 145667196661SRafal Jaworowski send = 1; 145767196661SRafal Jaworowski } 145867196661SRafal Jaworowski bus_dmamap_sync(sc->tsec_tx_dtag, sc->tsec_tx_dmap, 145967196661SRafal Jaworowski BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 146067196661SRafal Jaworowski 146167196661SRafal Jaworowski if (send) { 146267196661SRafal Jaworowski /* Now send anything that was pending */ 146367196661SRafal Jaworowski ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 146467196661SRafal Jaworowski tsec_start_locked(ifp); 146567196661SRafal Jaworowski 146667196661SRafal Jaworowski /* Stop wathdog if all sent */ 146767196661SRafal Jaworowski if (TSEC_EMPTYQ_TX_MBUF(sc)) 146867196661SRafal Jaworowski ifp->if_timer = 0; 146967196661SRafal Jaworowski } 147067196661SRafal Jaworowski TSEC_TRANSMIT_UNLOCK(sc); 147167196661SRafal Jaworowski } 147267196661SRafal Jaworowski 147367196661SRafal Jaworowski static void 147467196661SRafal Jaworowski tsec_error_intr(void *arg) 147567196661SRafal Jaworowski { 147667196661SRafal Jaworowski struct tsec_softc *sc = arg; 147767196661SRafal Jaworowski struct ifnet *ifp; 147867196661SRafal Jaworowski uint32_t eflags; 147967196661SRafal Jaworowski 148067196661SRafal Jaworowski ifp = sc->tsec_ifp; 148167196661SRafal Jaworowski 148267196661SRafal Jaworowski eflags = TSEC_READ(sc, TSEC_REG_IEVENT); 148367196661SRafal Jaworowski 148467196661SRafal Jaworowski if (ifp->if_flags & IFF_DEBUG) 148567196661SRafal Jaworowski if_printf(ifp, "tsec_error_intr(): event flags: 0x%x\n", eflags); 148667196661SRafal Jaworowski 148767196661SRafal Jaworowski /* Clear events bits in hardware */ 148867196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_IEVENT, TSEC_IEVENT_RXC | TSEC_IEVENT_BSY | 148967196661SRafal Jaworowski TSEC_IEVENT_EBERR | TSEC_IEVENT_MSRO | TSEC_IEVENT_BABT | 149067196661SRafal Jaworowski TSEC_IEVENT_TXC | TSEC_IEVENT_TXE | TSEC_IEVENT_LC | 149167196661SRafal Jaworowski TSEC_IEVENT_CRL | TSEC_IEVENT_XFUN); 149267196661SRafal Jaworowski 149367196661SRafal Jaworowski if (eflags & TSEC_IEVENT_EBERR) 149467196661SRafal Jaworowski if_printf(ifp, "System bus error occurred during" 149567196661SRafal Jaworowski " a DMA transaction (flags: 0x%x)\n", eflags); 149667196661SRafal Jaworowski 149767196661SRafal Jaworowski /* Check transmitter errors */ 149867196661SRafal Jaworowski if (eflags & TSEC_IEVENT_TXE) { 149967196661SRafal Jaworowski ifp->if_oerrors++; 150067196661SRafal Jaworowski 150167196661SRafal Jaworowski if (eflags & TSEC_IEVENT_LC) 150267196661SRafal Jaworowski ifp->if_collisions++; 150367196661SRafal Jaworowski 150467196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_TSTAT, TSEC_TSTAT_THLT); 150567196661SRafal Jaworowski } 150667196661SRafal Jaworowski if (eflags & TSEC_IEVENT_BABT) 150767196661SRafal Jaworowski ifp->if_oerrors++; 150867196661SRafal Jaworowski 150967196661SRafal Jaworowski /* Check receiver errors */ 151067196661SRafal Jaworowski if (eflags & TSEC_IEVENT_BSY) { 151167196661SRafal Jaworowski ifp->if_ierrors++; 151267196661SRafal Jaworowski ifp->if_iqdrops++; 151367196661SRafal Jaworowski 151467196661SRafal Jaworowski /* Get data from RX buffers */ 151567196661SRafal Jaworowski tsec_receive_intr(arg); 151667196661SRafal Jaworowski 151767196661SRafal Jaworowski /* Make receiver again active */ 151867196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_RSTAT, TSEC_RSTAT_QHLT); 151967196661SRafal Jaworowski } 152067196661SRafal Jaworowski if (eflags & TSEC_IEVENT_BABR) 152167196661SRafal Jaworowski ifp->if_ierrors++; 152267196661SRafal Jaworowski } 152367196661SRafal Jaworowski 152467196661SRafal Jaworowski static void 152567196661SRafal Jaworowski tsec_tick(void *arg) 152667196661SRafal Jaworowski { 152767196661SRafal Jaworowski struct tsec_softc *sc = arg; 152867196661SRafal Jaworowski struct ifnet *ifp; 152967196661SRafal Jaworowski int link; 153067196661SRafal Jaworowski 153167196661SRafal Jaworowski TSEC_TRANSMIT_LOCK(sc); 153267196661SRafal Jaworowski 153367196661SRafal Jaworowski ifp = sc->tsec_ifp; 153467196661SRafal Jaworowski link = sc->tsec_link; 153567196661SRafal Jaworowski 153667196661SRafal Jaworowski mii_tick(sc->tsec_mii); 153767196661SRafal Jaworowski 153867196661SRafal Jaworowski if (link == 0 && sc->tsec_link == 1 && (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))) 153967196661SRafal Jaworowski tsec_start_locked(ifp); 154067196661SRafal Jaworowski 154167196661SRafal Jaworowski callout_reset(&sc->tsec_tick_ch, hz, tsec_tick, sc); 154267196661SRafal Jaworowski TSEC_TRANSMIT_UNLOCK(sc); 154367196661SRafal Jaworowski } 154467196661SRafal Jaworowski 154567196661SRafal Jaworowski static int 154667196661SRafal Jaworowski tsec_miibus_readreg(device_t dev, int phy, int reg) 154767196661SRafal Jaworowski { 154867196661SRafal Jaworowski struct tsec_softc *sc; 154967196661SRafal Jaworowski uint32_t timeout; 155067196661SRafal Jaworowski 155167196661SRafal Jaworowski sc = device_get_softc(dev); 155267196661SRafal Jaworowski 155367196661SRafal Jaworowski if (device_get_unit(dev) != phy) 155467196661SRafal Jaworowski return (0); 155567196661SRafal Jaworowski 155667196661SRafal Jaworowski sc = tsec0_sc; 155767196661SRafal Jaworowski 155867196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_MIIMADD, (phy << 8) | reg); 155967196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_MIIMCOM, 0); 156067196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_MIIMCOM, TSEC_MIIMCOM_READCYCLE); 156167196661SRafal Jaworowski 156267196661SRafal Jaworowski timeout = TSEC_READ_RETRY; 156367196661SRafal Jaworowski while (--timeout && TSEC_READ(sc, TSEC_REG_MIIMIND) & 156467196661SRafal Jaworowski (TSEC_MIIMIND_NOTVALID | TSEC_MIIMIND_BUSY)) 156567196661SRafal Jaworowski DELAY(TSEC_READ_DELAY); 156667196661SRafal Jaworowski 156767196661SRafal Jaworowski if (timeout == 0) 156867196661SRafal Jaworowski device_printf(dev, "Timeout while reading from PHY!\n"); 156967196661SRafal Jaworowski 157067196661SRafal Jaworowski return (TSEC_READ(sc, TSEC_REG_MIIMSTAT)); 157167196661SRafal Jaworowski } 157267196661SRafal Jaworowski 157367196661SRafal Jaworowski static void 157467196661SRafal Jaworowski tsec_miibus_writereg(device_t dev, int phy, int reg, int value) 157567196661SRafal Jaworowski { 157667196661SRafal Jaworowski struct tsec_softc *sc; 157767196661SRafal Jaworowski uint32_t timeout; 157867196661SRafal Jaworowski 157967196661SRafal Jaworowski sc = device_get_softc(dev); 158067196661SRafal Jaworowski 158167196661SRafal Jaworowski if (device_get_unit(dev) != phy) 158267196661SRafal Jaworowski device_printf(dev, "Trying to write to an alien PHY(%d)\n", phy); 158367196661SRafal Jaworowski 158467196661SRafal Jaworowski sc = tsec0_sc; 158567196661SRafal Jaworowski 158667196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_MIIMADD, (phy << 8) | reg); 158767196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_MIIMCON, value); 158867196661SRafal Jaworowski 158967196661SRafal Jaworowski timeout = TSEC_READ_RETRY; 159067196661SRafal Jaworowski while (--timeout && (TSEC_READ(sc, TSEC_REG_MIIMIND) & TSEC_MIIMIND_BUSY)) 159167196661SRafal Jaworowski DELAY(TSEC_READ_DELAY); 159267196661SRafal Jaworowski 159367196661SRafal Jaworowski if (timeout == 0) 159467196661SRafal Jaworowski device_printf(dev, "Timeout while writing to PHY!\n"); 159567196661SRafal Jaworowski } 159667196661SRafal Jaworowski 159767196661SRafal Jaworowski static void 159867196661SRafal Jaworowski tsec_miibus_statchg(device_t dev) 159967196661SRafal Jaworowski { 160067196661SRafal Jaworowski struct tsec_softc *sc; 160167196661SRafal Jaworowski struct mii_data *mii; 160267196661SRafal Jaworowski uint32_t ecntrl, id, tmp; 160367196661SRafal Jaworowski int link; 160467196661SRafal Jaworowski 160567196661SRafal Jaworowski sc = device_get_softc(dev); 160667196661SRafal Jaworowski mii = sc->tsec_mii; 160767196661SRafal Jaworowski link = ((mii->mii_media_status & IFM_ACTIVE) ? 1 : 0); 160867196661SRafal Jaworowski 160967196661SRafal Jaworowski tmp = TSEC_READ(sc, TSEC_REG_MACCFG2) & ~TSEC_MACCFG2_IF; 161067196661SRafal Jaworowski 161167196661SRafal Jaworowski if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) 161267196661SRafal Jaworowski tmp |= TSEC_MACCFG2_FULLDUPLEX; 161367196661SRafal Jaworowski else 161467196661SRafal Jaworowski tmp &= ~TSEC_MACCFG2_FULLDUPLEX; 161567196661SRafal Jaworowski 161667196661SRafal Jaworowski switch (IFM_SUBTYPE(mii->mii_media_active)) { 161767196661SRafal Jaworowski case IFM_1000_T: 161867196661SRafal Jaworowski case IFM_1000_SX: 161967196661SRafal Jaworowski tmp |= TSEC_MACCFG2_GMII; 162067196661SRafal Jaworowski sc->tsec_link = link; 162167196661SRafal Jaworowski break; 162267196661SRafal Jaworowski case IFM_100_TX: 162367196661SRafal Jaworowski case IFM_10_T: 162467196661SRafal Jaworowski tmp |= TSEC_MACCFG2_MII; 162567196661SRafal Jaworowski sc->tsec_link = link; 162667196661SRafal Jaworowski break; 162767196661SRafal Jaworowski case IFM_NONE: 162867196661SRafal Jaworowski if (link) 162967196661SRafal Jaworowski device_printf(dev, "No speed selected but link active!\n"); 163067196661SRafal Jaworowski sc->tsec_link = 0; 163167196661SRafal Jaworowski return; 163267196661SRafal Jaworowski default: 163367196661SRafal Jaworowski sc->tsec_link = 0; 163467196661SRafal Jaworowski device_printf(dev, "Unknown speed (%d), link %s!\n", 163567196661SRafal Jaworowski IFM_SUBTYPE(mii->mii_media_active), 163667196661SRafal Jaworowski ((link) ? "up" : "down")); 163767196661SRafal Jaworowski return; 163867196661SRafal Jaworowski } 163967196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_MACCFG2, tmp); 164067196661SRafal Jaworowski 164167196661SRafal Jaworowski /* XXX kludge - use circumstantial evidence for reduced mode. */ 164267196661SRafal Jaworowski id = TSEC_READ(sc, TSEC_REG_ID2); 164367196661SRafal Jaworowski if (id & 0xffff) { 164467196661SRafal Jaworowski ecntrl = TSEC_READ(sc, TSEC_REG_ECNTRL) & ~TSEC_ECNTRL_R100M; 164567196661SRafal Jaworowski ecntrl |= (tmp & TSEC_MACCFG2_MII) ? TSEC_ECNTRL_R100M : 0; 164667196661SRafal Jaworowski TSEC_WRITE(sc, TSEC_REG_ECNTRL, ecntrl); 164767196661SRafal Jaworowski } 164867196661SRafal Jaworowski } 1649